From 578d5c0a8d8a908d1053ae361564e01a755695e3 Mon Sep 17 00:00:00 2001 From: Maximilian Attems Date: Sat, 26 Apr 2008 21:59:14 +0000 Subject: [PATCH] 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 svn path=/dists/trunk/linux-2.6/; revision=11188 --- debian/patches/bugfix/all/patch-2.6.25-git9 | 952011 +++++++++++++++++ debian/patches/series/1~experimental.1 | 1 + 2 files changed, 952012 insertions(+) create mode 100644 debian/patches/bugfix/all/patch-2.6.25-git9 diff --git a/debian/patches/bugfix/all/patch-2.6.25-git9 b/debian/patches/bugfix/all/patch-2.6.25-git9 new file mode 100644 index 000000000..b241a2899 --- /dev/null +++ b/debian/patches/bugfix/all/patch-2.6.25-git9 @@ -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@mo.himolde.no + D: Misc kernel hacks ++D: Updated PC speaker driver for 2.3 ++S: Norway + + N: Andreas E. Bombe + E: andreas.bombe@munich.netsurf.de +@@ -3116,6 +3118,12 @@ S: Post Office Box 64132 + S: Sunnyvale, California 94088-4132 + S: USA + ++N: Stas Sergeev ++E: stsp@users.sourceforge.net ++D: PCM PC-Speaker driver ++D: misc fixes ++S: Russia ++ + N: Simon Shapiro + E: shimon@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@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@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@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@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 ++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 ++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 ++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 ++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 ++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 ++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 ++Description: ++ Major and minor numbers of the character device corresponding ++ to this UBI device (in : format). ++ ++What: /sys/class/ubi/ubiX/eraseblock_size ++Date: July 2006 ++KernelVersion: 2.6.22 ++Contact: Artem Bityutskiy ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++Description: ++ Major and minor numbers of the character device corresponding ++ to this UBI volume (in : format). ++ ++What: /sys/class/ubi/ubiX/ubiX_Y/name ++Date: July 2006 ++KernelVersion: 2.6.22 ++Contact: Artem Bityutskiy ++Description: ++ Volume name. ++ ++What: /sys/class/ubi/ubiX/ubiX_Y/reserved_ebs ++Date: July 2006 ++KernelVersion: 2.6.22 ++Contact: Artem Bityutskiy ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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@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@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@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@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@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 +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 ""; \ + 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 + + +- +- Power Management +-!Ekernel/power/pm.c +- +- + + Device drivers infrastructure + Device Drivers Base +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 @@ + + + The third type is a semaphore +- (include/asm/semaphore.h): it ++ (include/linux/semaphore.h): 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 @@ + + If you have a data structure which is only ever accessed from + user context, then you can use a simple semaphore +- (linux/asm/semaphore.h) to protect it. This ++ (linux/linux/semaphore.h) to protect it. This + is the most trivial case: you initialize the semaphore to the number + of resources available (usually 1), and call + down_interruptible() 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 @@ ++ ++ ++ ++ ++ ++ Using kgdb and the kgdb Internals ++ ++ ++ ++ Jason ++ Wessel ++ ++
++ jason.wessel@windriver.com ++
++
++
++
++ ++ ++ ++ Tom ++ Rini ++ ++
++ trini@kernel.crashing.org ++
++
++
++
++ ++ ++ ++ Amit S. ++ Kale ++ ++
++ amitkale@linsyssoft.com ++
++
++
++
++ ++ ++ 2008 ++ Wind River Systems, Inc. ++ ++ ++ 2004-2005 ++ MontaVista Software, Inc. ++ ++ ++ 2004 ++ Amit S. Kale ++ ++ ++ ++ ++ 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. ++ ++ ++ ++
++ ++ ++ ++ Introduction ++ ++ 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. ++ ++ ++ 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. ++ ++ ++ ++ Compiling a kernel ++ ++ To enable CONFIG_KGDB, look under the "Kernel debugging" ++ and then select "KGDB: kernel debugging with remote gdb". ++ ++ ++ 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. ++ ++ ++ The kgdb test compile options are described in the kgdb test suite chapter. ++ ++ ++ ++ ++ Enable kgdb for debugging ++ ++ 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. ++ ++ ++ All drivers can be reconfigured at run time, if ++ CONFIG_SYSFS and CONFIG_MODULES ++ are enabled, by echo'ing a new config string to ++ /sys/module/<driver>/parameter/<option>. ++ 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 detach command ++ prior to trying unconfigure a kgdb I/O driver. ++ ++ ++ Kernel parameter: kgdbwait ++ ++ The Kernel command line option kgdbwait 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. ++ ++ ++ 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. ++ ++ ++ ++ Kernel parameter: kgdboc ++ ++ 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. ++ ++ ++ Using kgdboc ++ ++ 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. ++ ++ From the module load or build-in ++ kgdboc=<tty-device>,[baud] ++ ++ The example here would be if your console port was typically ttyS0, you would use something like kgdboc=ttyS0,115200 or on the ARM Versatile AB you would likely use kgdboc=ttyAMA0,115200 ++ ++ ++ From sysfs ++ echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc ++ ++ ++ ++ ++ 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. ++ ++ 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 g. 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. ++ ++ ++ ++ ++ Kernel parameter: kgdbcon ++ ++ 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. ++ ++ Activate with the kernel command line option: ++ kgdbcon ++ ++ Use sysfs before configuring an io driver ++ ++ echo 1 > /sys/module/kgdb/parameters/kgdb_use_con ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ IMPORTANT NOTE: Using this option with kgdb over the console ++ (kgdboc) or kgdb over ethernet (kgdboe) is not supported. ++ ++ ++ ++ ++ Connecting gdb ++ ++ 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. ++ ++ ++ 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. ++ ++ ++ Example (using a serial port): ++ ++ ++ % gdb ./vmlinux ++ (gdb) set remotebaud 115200 ++ (gdb) target remote /dev/ttyS0 ++ ++ ++ Example (kgdb to a terminal server): ++ ++ ++ % gdb ./vmlinux ++ (gdb) target remote udp:192.168.2.2:6443 ++ ++ ++ Example (kgdb over ethernet): ++ ++ ++ % gdb ./vmlinux ++ (gdb) target remote udp:192.168.2.2:6443 ++ ++ ++ Once connected, you can debug a kernel the way you would debug an ++ application program. ++ ++ ++ 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 target ++ remote command by typing in: set remote debug 1 ++ ++ ++ ++ kgdb Test Suite ++ ++ 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. ++ ++ ++ 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. ++ ++ ++ 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. ++ ++ ++ ++ KGDB Internals ++ ++ Architecture Specifics ++ ++ Kgdb is organized into three basic components: ++ ++ kgdb core ++ ++ The kgdb core is found in kernel/kgdb.c. It contains: ++ ++ All the logic to implement the gdb serial protocol ++ A generic OS exception handler which includes sync'ing the processors into a stopped state on an multi cpu system. ++ The API to talk to the kgdb I/O drivers ++ The API to make calls to the arch specific kgdb implementation ++ The logic to perform safe memory reads and writes to memory while using the debugger ++ A full implementation for software breakpoints unless overridden by the arch ++ ++ ++ ++ kgdb arch specific implementation ++ ++ 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: ++ ++ contains an arch specific trap catcher which ++ invokes kgdb_handle_exception() to start kgdb about doing its ++ work ++ translation to and from gdb specific packet format to pt_regs ++ Registration and unregistration of architecture specific trap hooks ++ Any special exception handling and cleanup ++ NMI exception handling and cleanup ++ (optional)HW breakpoints ++ ++ ++ ++ kgdb I/O driver ++ ++ Each kgdb I/O driver has to provide an implemenation for the following: ++ ++ configuration via builtin or module ++ dynamic configuration and kgdb hook registration calls ++ read and write character interface ++ A cleanup handler for unconfiguring from the kgdb core ++ (optional) Early debug methodology ++ ++ 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. ++ ++ ++ ++ ++ ++ If you are intent on adding kgdb architecture specific support ++ for a new architecture, the architecture should define ++ HAVE_ARCH_KGDB 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. ++ ++ ++ There are a few flags which must be set on every architecture in ++ their <asm/kgdb.h> file. These are: ++ ++ ++ ++ NUMREGBYTES: The size in bytes of all of the registers, so ++ that we can ensure they will all fit into a packet. ++ ++ ++ BUFMAX: The size in bytes of the buffer GDB will read into. ++ This must be larger than NUMREGBYTES. ++ ++ ++ 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. ++ ++ ++ ++ ++ ++ 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. ++ ++!Iinclude/linux/kgdb.h ++ ++ ++ kgdboc internals ++ ++ 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. ++ ++ ++ When using kgdboc with a uart, the uart driver must implement two callbacks in the struct uart_ops. Example from drivers/8250.c: ++#ifdef CONFIG_CONSOLE_POLL ++ .poll_get_char = serial8250_get_poll_char, ++ .poll_put_char = serial8250_put_poll_char, ++#endif ++ ++ Any implementation specifics around creating a polling driver use the ++ #ifdef CONFIG_CONSOLE_POLL, 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. ++ ++ ++ ++ ++ Credits ++ ++ The following people have contributed to this document: ++ ++ Amit Kaleamitkale@linsyssoft.com ++ Tom Rinitrini@kernel.crashing.org ++ ++ In March 2008 this document was completely rewritten by: ++ ++ Jason Wesseljason.wessel@windriver.com ++ ++ ++ ++
++ +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 @@ ++ ++ ++ ++ ++ ++ The mac80211 subsystem for kernel developers ++ ++ ++ ++ Johannes ++ Berg ++ ++
johannes@sipsolutions.net
++
++
++
++ ++ ++ 2007 ++ 2008 ++ Johannes Berg ++ ++ ++ ++ ++ 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. ++ ++ ++ ++ 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. ++ ++ ++ ++ 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 ++ ++ ++ ++ For more details see the file COPYING in the source ++ distribution of Linux. ++ ++ ++ ++ ++!Pinclude/net/mac80211.h Introduction ++!Pinclude/net/mac80211.h Warning ++ ++
++ ++ ++ ++ ++ ++ ++ The basic mac80211 driver interface ++ ++ ++ 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. ++ ++ ++ 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. ++ ++ ++ ++ ++ Basic hardware handling ++ TBD ++ ++ This chapter shall contain information on getting a hw ++ struct allocated and registered with mac80211. ++ ++ ++ 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. ++ ++ ++ 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. ++ ++ ++ Finally, a discussion of hardware capabilities should be done ++ with references to other parts of the book. ++ ++ ++!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 ++ ++ ++ ++ PHY configuration ++ TBD ++ ++ This chapter should describe PHY handling including ++ start/stop callbacks and the various structures used. ++ ++!Finclude/net/mac80211.h ieee80211_conf ++!Finclude/net/mac80211.h ieee80211_conf_flags ++ ++ ++ ++ Virtual interfaces ++ TBD ++ ++ 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. ++ ++ Things related to AP mode should be discussed there. ++ ++ 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! ++ ++!Finclude/net/mac80211.h ieee80211_if_types ++!Finclude/net/mac80211.h ieee80211_if_init_conf ++!Finclude/net/mac80211.h ieee80211_if_conf ++ ++ ++ ++ Receive and transmit processing ++ ++ what should be here ++ TBD ++ ++ This should describe the receive and transmit ++ paths in mac80211/the drivers as well as ++ transmit status handling. ++ ++ ++ ++ Frame format ++!Pinclude/net/mac80211.h Frame format ++ ++ ++ Alignment issues ++ TBD ++ ++ ++ Calling into mac80211 from interrupts ++!Pinclude/net/mac80211.h Calling mac80211 from interrupts ++ ++ ++ functions/definitions ++!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 ++ ++ ++ ++ ++ Frame filtering ++!Pinclude/net/mac80211.h Frame filtering ++!Finclude/net/mac80211.h ieee80211_filter_flags ++ ++ ++ ++ ++ Advanced driver interface ++ ++ ++ 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. ++ ++ ++ ++ ++ Hardware crypto acceleration ++!Pinclude/net/mac80211.h Hardware crypto acceleration ++ ++!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 ++ ++ ++ ++ Multiple queues and QoS support ++ TBD ++!Finclude/net/mac80211.h ieee80211_tx_queue_params ++!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data ++!Finclude/net/mac80211.h ieee80211_tx_queue ++ ++ ++ ++ Access point mode support ++ TBD ++ Some parts of the if_conf should be discussed here instead ++ ++ Insert notes about VLAN interfaces with hw crypto here or ++ in the hw crypto chapter. ++ ++!Finclude/net/mac80211.h ieee80211_get_buffered_bc ++!Finclude/net/mac80211.h ieee80211_beacon_get ++ ++ ++ ++ Supporting multiple virtual interfaces ++ TBD ++ ++ Note: WDS with identical MAC address should almost always be OK ++ ++ ++ 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. ++ ++ ++ ++ ++ Hardware scan offload ++ TBD ++!Finclude/net/mac80211.h ieee80211_scan_completed ++ ++ ++ ++ ++ Rate control interface ++ ++ TBD ++ ++ This part of the book describes the rate control algorithm ++ interface and how it relates to mac80211 and drivers. ++ ++ ++ ++ dummy chapter ++ TBD ++ ++ ++ ++ ++ Internals ++ ++ TBD ++ ++ This part of the book describes mac80211 internals. ++ ++ ++ ++ ++ Key handling ++ ++ Key handling basics ++!Pnet/mac80211/key.c Key handling basics ++ ++ ++ MORE TBD ++ TBD ++ ++ ++ ++ ++ Receive processing ++ TBD ++ ++ ++ ++ Transmit processing ++ TBD ++ ++ ++ ++ Station info handling ++ ++ Programming information ++!Fnet/mac80211/sta_info.h sta_info ++!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags ++ ++ ++ STA information lifetime rules ++!Pnet/mac80211/sta_info.c STA information lifetime rules ++ ++ ++ ++ ++ Synchronisation ++ TBD ++ Locking, lots of RCU ++ ++ ++
+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. +
+ + 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); +
+ +- 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: + + +@@ -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: + + + /* 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 , 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 + git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git + ++ - x86, Ingo Molnar ++ 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 ++ - USB, Driver Core, and I2C, Greg Kroah-Hartman + kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ +- - x86-64, partly i386, Andi Kleen +- 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@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 ++ ++ ++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 on 07-Feb-2000 ++ updated by Grant Grundler 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" 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 . ++ ++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 ): ++ ++ __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 . ++ ++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 ++ Yanmin Zhang ++ 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@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@kernel.org managed by Adrian Bunk; which collects "trivial" ++trivial@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: ++URL: + + + +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, $_dops$, while + it may have as many structures $_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 + Modified by Christoph Lameter + Modified by Paul Menage ++Modified by Hidetoshi Seto + + 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: ++ ++ ++ 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 used for encryption. It is encoded as a hexadecimal number. ++ You can only use key sizes that are valid for the selected cipher. ++ ++ ++ The IV offset is a sector count that is added to the sector number ++ before creating the IV. ++ ++ ++ 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 :. ++ ++ ++ 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@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 +- +---------------------------- +- + 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 + + --------------------------- + +---------------------------- +- + 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 + + --------------------------- + +-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 +- +---------------------------- +- +-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 +- +---------------------------- +- +-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 +- +---------------------------- +- + 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 + + --------------------------- + +-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 +- +---------------------------- +- + 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 ++ ++---------------------------- ++ ++What: usedac i386 kernel parameter ++When: 2.6.27 ++Why: replaced by allowdac and no dac combination ++Who: Glauber Costa ++ ++--------------------------- ++ ++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@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 +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@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 :/ /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//oom_score - Display current oom-killer score + 2.14 /proc//io - Display the IO accounting fields + 2.15 /proc//coredump_filter - Core dump filtering settings ++ 2.16 /proc//mountinfo - Information about mounts + + ------------------------------------------------------------------------------ + Preface +@@ -2348,4 +2349,41 @@ For example: + $ echo 0x7 > /proc/self/coredump_filter + $ ./some_program + ++2.16 /proc//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 +-#include +-#include +-#include +-#include +- +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +- +- +-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: [,[,[,]]] + + 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: [,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: ++ range: 0,4 : pattern number ++ default : 0 ++ + 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//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//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 ' +-will extract the microcode and write it to directory +-. 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@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 +-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@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@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 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 +- +- +-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 on 07-Feb-2000 +- updated by Grant Grundler 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" 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 . +- +-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 ): +- +- __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 . +- +-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 +- Yanmin Zhang +- 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 : 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@2000 { + device_type = "network"; + compatible = "ucc_geth"; +- model = "UCC"; +- device-id = <1>; ++ cell-index = <1>; + reg = <2000 200>; + interrupts = ; + 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@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@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@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@2000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "marvell,mv64360-eth-block"; ++ reg = <0x2000 0x2000>; ++ ethernet@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 : 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@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 : 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@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 : 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@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@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@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@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@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 : 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@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@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 : 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@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@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@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@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@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@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@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@1400 { ++ #gpio-cells = <2>; ++ compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank"; ++ reg = <0x1400 0x18>; ++ gpio-controller; ++ }; ++ ++ qe_pio_e: gpio-controller@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 ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++#include ++ ++/* 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 ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++#include ++ ++/* 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 ++#include ++#include ++#include ++#include ++ ++ ++#include ++#include ++ ++/* 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//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//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//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//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//cpu_rt_period_us" or ++"/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@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 +-Werner Almesberger +-Martin von Loewis +- +-Here is the problem: +- +- Suppose that drivers/net/foo.c has the following lines: +- +- #include +- +- ... +- +- #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 + +- 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@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@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@wantstofly.org + L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) + S: Maintained + ++ARM/GUMSTIX MACHINE SUPPORT ++P: Steve Sakoman ++M: sakoman@gmail.com ++L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) ++S: Maintained ++ + ARM/HP JORNADA 7XX MACHINE SUPPORT + P: Kristoffer Ericson + M: kristoffer.ericson@gmail.com +@@ -678,6 +684,11 @@ L: linux-wireless@vger.kernel.org + L: ath5k-devel@lists.ath5k.org + S: Maintained + ++ATI_REMOTE2 DRIVER ++P: Ville Syrjala ++M: syrjala@sci.fi ++S: Maintained ++ + ATL1 ETHERNET DRIVER + P: Jay Cliburn + M: jcliburn@gmail.com +@@ -840,15 +851,6 @@ L: linux-wireless@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@lwfinger.net +-P: Stefano Brivio +-M: stefano.brivio@polimi.it +-L: linux-wireless@vger.kernel.org +-W: http://bcm43xx.berlios.de/ +-S: Obsolete +- + BEFS FILE SYSTEM + P: Sergey S. Kostyliov + M: rathamahata@php4.ru +@@ -1104,6 +1106,12 @@ M: kernel@wantstofly.org + L: linux-usb@vger.kernel.org + S: Maintained + ++CIRRUS LOGIC CS4270 SOUND DRIVER ++P: Timur Tabi ++M: timur@freescale.com ++L: alsa-devel@alsa-project.org ++S: Supported ++ + CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER + P: Cirrus Logic Corporation (kernel 2.2 driver) + M: Cirrus Logic Corporation, Thomas Woller +@@ -1626,6 +1634,12 @@ L: linuxppc-dev@ozlabs.org + L: netdev@vger.kernel.org + S: Maintained + ++FREESCALE QUICC ENGINE LIBRARY ++P: Timur Tabi ++M: timur@freescale.com ++L: linuxppc-dev@ozlabs.org ++S: Supported ++ + FREESCALE HIGHSPEED USB DEVICE DRIVER + P: Li Yang + M: leoli@freescale.com +@@ -1640,6 +1654,19 @@ L: netdev@vger.kernel.org + L: linuxppc-dev@ozlabs.org + S: Maintained + ++FREESCALE QUICC ENGINE UCC UART DRIVER ++P: Timur Tabi ++M: timur@freescale.com ++L: linuxppc-dev@ozlabs.org ++S: Supported ++ ++FREESCALE SOC SOUND DRIVERS ++P: Timur Tabi ++M: timur@freescale.com ++L: alsa-devel@alsa-project.org ++L: linuxppc-dev@ozlabs.org ++S: Supported ++ + FILE LOCKING (flock() and fcntl()/lockf()) + P: Matthew Wilcox + M: matthew@wil.cx +@@ -2319,6 +2346,12 @@ L: linux-kernel@vger.kernel.org + L: kexec@lists.infradead.org + S: Maintained + ++KGDB ++P: Jason Wessel ++M: jason.wessel@windriver.com ++L: kgdb-bugreport@lists.sourceforge.net ++S: Maintained ++ + KPROBES + P: Ananth N Mavinakayanahalli + M: ananth@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@sourmilk.net + P: Johannes Berg + M: johannes@sipsolutions.net +-P: Jiri Benc +-M: jbenc@suse.cz ++P: Michael Wu ++M: flamingice@sourmilk.net + L: linux-wireless@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@suse.com + P: Joel Becker + M: joel.becker@oracle.com +-L: ocfs2-devel@oss.oracle.com ++L: ocfs2-devel@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@atrey.karlin.mff.cuni.cz + S: Supported + + PCI SUBSYSTEM +-P: Greg Kroah-Hartman +-M: gregkh@suse.de ++P: Jesse Barnes ++M: jbarnes@virtuousgeek.org + L: linux-kernel@vger.kernel.org + L: linux-pci@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@hp.com + P: Sridhar Samudrala + M: sri@us.ibm.com +-L: lksctp-developers@lists.sourceforge.net ++L: linux-sctp@vger.kernel.org + W: http://lksctp.sourceforge.net + S: Supported + +@@ -3606,11 +3637,10 @@ M: mhoffman@lightlink.com + L: lm-sensors@lm-sensors.org + S: Maintained + +-SOFTMAC LAYER (IEEE 802.11) +-P: Daniel Drake +-M: dsd@gentoo.org +-L: linux-wireless@vger.kernel.org +-S: Obsolete ++SMX UIO Interface ++P: Ben Nizette ++M: bn@niasdigital.com ++S: Maintained + + SOFTWARE RAID (Multiple Disks) SUPPORT + P: Ingo Molnar +@@ -4351,6 +4381,16 @@ L: linux-wireless@vger.kernel.org + W: http://oops.ghostprotocols.net:81/blog + S: Maintained + ++WM97XX TOUCHSCREEN DRIVERS ++P: Mark Brown ++M: broonie@opensource.wolfsonmicro.com ++P: Liam Girdwood ++M: liam.girdwood@wolfsonmicro.com ++L: linux-input@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@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 +-#include +-#include +- +-/* +- * 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) 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) 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) 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 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 + + #include +-#include + + 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 + #include + #include ++#include + #include + + /* 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 +-#include +-#include +-#include +- +-#include +- +-/* +- * 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 +- * 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 ++#include ++ ++#include ++ ++/* ++ * 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 + #include + +-#include +- + #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. ++ ++ + endif + + # ---------------------------------------------------------- +@@ -133,6 +150,20 @@ config MACH_AT91SAM9260EK + Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit + + ++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. ++ ++ ++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. ++ ++ + 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 ++#include + + #include + #include + #include + #include + #include ++#include + + #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 + #include +-#include ++#include + + #include ; /* 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 = ; ++ 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@0,0 { ++ compatible = "amd,s29gl512n", "cfi-flash"; ++ bank-width = <2>; ++ reg = <0 000000 4000000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ partition@0 { ++ label = "kernel"; ++ reg = <0 1e0000>; ++ }; ++ partition@1e0000 { ++ label = "dtb"; ++ reg = <1e0000 20000>; ++ }; ++ partition@200000 { ++ label = "ramdisk"; ++ reg = <200000 1400000>; ++ }; ++ partition@1600000 { ++ label = "jffs2"; ++ reg = <1600000 400000>; ++ }; ++ partition@1a00000 { ++ label = "user"; ++ reg = <1a00000 2560000>; ++ }; ++ partition@3f60000 { ++ label = "env"; ++ reg = <3f60000 40000>; ++ }; ++ partition@3fa0000 { ++ label = "u-boot"; ++ reg = <3fa0000 60000>; ++ }; ++ }; ++ }; ++ ++ UART0: serial@ef600300 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC1>; ++ interrupts = <1 4>; ++ }; ++ ++ UART1: serial@ef600400 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC0>; ++ interrupts = <1 4>; ++ }; ++ ++ UART2: serial@ef600500 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC1>; ++ interrupts = <1d 4>; ++ }; ++ ++ UART3: serial@ef600600 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC1>; ++ interrupts = <1e 4>; ++ }; ++ ++ IIC0: i2c@ef600700 { ++ compatible = "ibm,iic-460ex", "ibm,iic"; ++ reg = ; ++ interrupt-parent = <&UIC0>; ++ interrupts = <2 4>; ++ }; ++ ++ IIC1: i2c@ef600800 { ++ compatible = "ibm,iic-460ex", "ibm,iic"; ++ reg = ; ++ interrupt-parent = <&UIC0>; ++ interrupts = <3 4>; ++ }; ++ ++ ZMII0: emac-zmii@ef600d00 { ++ compatible = "ibm,zmii-460ex", "ibm,zmii"; ++ reg = ; ++ }; ++ ++ RGMII0: emac-rgmii@ef601500 { ++ compatible = "ibm,rgmii-460ex", "ibm,rgmii"; ++ reg = ; ++ has-mdio; ++ }; ++ ++ TAH0: emac-tah@ef601350 { ++ compatible = "ibm,tah-460ex", "ibm,tah"; ++ reg = ; ++ }; ++ ++ TAH1: emac-tah@ef601450 { ++ compatible = "ibm,tah-460ex", "ibm,tah"; ++ reg = ; ++ }; ++ ++ EMAC0: ethernet@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 = ; ++ reg = ; ++ 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@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 = ; ++ reg = ; ++ 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@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 = ; /* 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@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 = ; /* 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@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 = ; /* 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@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@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@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@0 { + device_type = "cpu"; +- reg = <0>; +- d-cache-line-size = ; +- i-cache-line-size = ; +- d-cache-size = ; +- i-cache-size = ; ++ 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 = ; // decrementer interrupt ++ interrupts = <15 2>; // decrementer interrupt + interrupt-parent = <&PIC>; + }; + }; + + memory { + device_type = "memory"; +- reg = <0 0>; ++ reg = <0x0 0x0>; + }; + + localbus@fa200100 { + compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus"; + #address-cells = <2>; + #size-cells = <1>; +- reg = ; ++ reg = <0xfa200100 0x40>; + + ranges = < +- 0 0 fc000000 04000000 +- 3 0 fa000000 01000000 ++ 0x0 0x0 0xfc000000 0x4000000 ++ 0x3 0x0 0xfa000000 0x1000000 + >; + + flash@0,2000000 { + compatible = "cfi-flash"; +- reg = <0 2000000 2000000>; ++ reg = <0x0 0x2000000 0x2000000>; + bank-width = <4>; + device-width = <2>; + }; + + board-control@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 = ; ++ reg = <0xfa200000 0x4000>; + + mdio@e00 { + compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio"; +- reg = ; ++ reg = <0xe00 0x188>; + #address-cells = <1>; + #size-cells = <0>; + + PHY0: ethernet-phy@0 { +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + + PHY1: ethernet-phy@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 = ; ++ 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@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 = ; ++ interrupts = <13 1>; + }; + + cpm@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@2000 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 2000 2000>; ++ ranges = <0x0 0x2000 0x2000>; + + data@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@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 = ; ++ 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 = ; +- 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 = ; ++ 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 ++ * ++ * 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@0>; ++ ++ aliases { ++ ethernet0 = &EMAC0; ++ ethernet1 = &EMAC1; ++ ethernet2 = &EMAC2; ++ ethernet3 = &EMAC3; ++ serial0 = &UART0; ++ serial1 = &UART1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@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 = ; /* 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 = ; ++ 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@0,0 { ++ compatible = "amd,s29gl512n", "cfi-flash"; ++ bank-width = <2>; ++ reg = <0 000000 4000000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ partition@0 { ++ label = "kernel"; ++ reg = <0 1e0000>; ++ }; ++ partition@1e0000 { ++ label = "dtb"; ++ reg = <1e0000 20000>; ++ }; ++ partition@200000 { ++ label = "ramdisk"; ++ reg = <200000 1400000>; ++ }; ++ partition@1600000 { ++ label = "jffs2"; ++ reg = <1600000 400000>; ++ }; ++ partition@1a00000 { ++ label = "user"; ++ reg = <1a00000 2560000>; ++ }; ++ partition@3f60000 { ++ label = "env"; ++ reg = <3f60000 40000>; ++ }; ++ partition@3fa0000 { ++ label = "u-boot"; ++ reg = <3fa0000 60000>; ++ }; ++ }; ++ }; ++ ++ UART0: serial@ef600300 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC1>; ++ interrupts = <1 4>; ++ }; ++ ++ UART1: serial@ef600400 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC0>; ++ interrupts = <1 4>; ++ }; ++ ++ UART2: serial@ef600500 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC1>; ++ interrupts = <1d 4>; ++ }; ++ ++ UART3: serial@ef600600 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by U-Boot */ ++ current-speed = <0>; /* Filled in by U-Boot */ ++ interrupt-parent = <&UIC1>; ++ interrupts = <1e 4>; ++ }; ++ ++ IIC0: i2c@ef600700 { ++ compatible = "ibm,iic-460gt", "ibm,iic"; ++ reg = ; ++ interrupt-parent = <&UIC0>; ++ interrupts = <2 4>; ++ }; ++ ++ IIC1: i2c@ef600800 { ++ compatible = "ibm,iic-460gt", "ibm,iic"; ++ reg = ; ++ interrupt-parent = <&UIC0>; ++ interrupts = <3 4>; ++ }; ++ ++ ZMII0: emac-zmii@ef600d00 { ++ compatible = "ibm,zmii-460gt", "ibm,zmii"; ++ reg = ; ++ }; ++ ++ RGMII0: emac-rgmii@ef601500 { ++ compatible = "ibm,rgmii-460gt", "ibm,rgmii"; ++ reg = ; ++ has-mdio; ++ }; ++ ++ RGMII1: emac-rgmii@ef601600 { ++ compatible = "ibm,rgmii-460gt", "ibm,rgmii"; ++ reg = ; ++ has-mdio; ++ }; ++ ++ TAH0: emac-tah@ef601350 { ++ compatible = "ibm,tah-460gt", "ibm,tah"; ++ reg = ; ++ }; ++ ++ TAH1: emac-tah@ef601450 { ++ compatible = "ibm,tah-460gt", "ibm,tah"; ++ reg = ; ++ }; ++ ++ EMAC0: ethernet@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 = ; ++ reg = ; ++ 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@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 = ; ++ reg = ; ++ 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@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 = ; ++ reg = ; ++ 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@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 = ; ++ reg = ; ++ 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@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 = ; /* 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@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 = ; /* 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@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 = ; /* 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@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 ++ * ++ * 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@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@fdf00000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ ranges = <0x00000000 0xfdf00000 0x00100000>; ++ bus-frequency = <0>; /* Fixed by bootwrapper */ ++ ++ memory-controller@2000 { ++ compatible = "fsl,8540-memory-controller"; ++ reg = <0x2000 0x1000>; ++ interrupt-parent = <&MPIC>; ++ interrupts = <0x12 0x2>; ++ }; ++ ++ l2-cache-controller@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@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <0x2b 0x2>; ++ interrupt-parent = <&MPIC>; ++ dfsrr; ++ }; ++ ++ mdio@24520 { /* For TSECs */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ ++ PHY1: ethernet-phy@1 { ++ interrupt-parent = <&MPIC>; ++ reg = <0x1>; ++ device_type = "ethernet-phy"; ++ }; ++ ++ PHY2: ethernet-phy@2 { ++ interrupt-parent = <&MPIC>; ++ reg = <0x2>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ enet0: ethernet@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@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@40000 { ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ reg = <0x40000 0x40000>; ++ device_type = "open-pic"; ++ }; ++ ++ cpm@919c0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8560-cpm", "fsl,cpm2"; ++ reg = <0x919c0 0x30>; ++ ranges; ++ ++ muram@80000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x80000 0x10000>; ++ ++ data@0 { ++ compatible = "fsl,cpm-muram-data"; ++ reg = <0x0 0x4000 0x9000 0x2000>; ++ }; ++ }; ++ ++ brg@919f0 { ++ compatible = "fsl,mpc8560-brg", ++ "fsl,cpm2-brg", ++ "fsl,cpm-brg"; ++ reg = <0x919f0 0x10 0x915f0 0x10>; ++ clock-frequency = <165000000>; /* 166MHz */ ++ }; ++ ++ CPMPIC: pic@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@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@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@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@0 { ++ interrupt-parent = <&MPIC>; ++ reg = <0x0>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ enet2: ethernet@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@fdf05000 { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8560-localbus"; ++ reg = <0xfdf05000 0x68>; ++ ++ ranges = <0x0 0x0 0xe0000000 0x00800000 ++ 0x4 0x0 0xe8080000 0x00080000>; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec-flash"; ++ reg = <0x0 0x0 0x800000>; ++ bank-width = <0x2>; ++ ++ partition@0 { ++ label = "Primary Kernel"; ++ reg = <0x0 0x180000>; ++ }; ++ partition@180000 { ++ label = "Primary Filesystem"; ++ reg = <0x180000 0x580000>; ++ }; ++ partition@700000 { ++ label = "Monitor"; ++ reg = <0x300000 0x100000>; ++ read-only; ++ }; ++ }; ++ ++ cpld@4,0 { ++ compatible = "emerson,KSI8560-cpld"; ++ reg = <0x4 0x0 0x80000>; ++ }; ++ }; ++ ++ ++ chosen { ++ linux,stdout-path = "/soc/cpm/serial@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 ++ * 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 = ; /* 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@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@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 = ; +- interrupts = ; ++ 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@fec00000 { +@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ?? + #interrupt-cells = <1>; + device_type = "pci"; + compatible = "mpc10x-pci"; +- reg = ; +- 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 = ; ++ 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 ++ * 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 = ; /* 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@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@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 = ; +- interrupts = ; ++ 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@fec00000 { +@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ?? + #interrupt-cells = <1>; + device_type = "pci"; + compatible = "mpc10x-pci"; +- reg = ; +- 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 = ; ++ 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 . + * + * 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@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 = ; ++ ranges = <0x0 0xc0000000 0x10000>; ++ reg = <0xc0000000 0x10000>; + bus-frequency = <0>; + + i2c@7000 { + interrupt-parent = <&mpic>; +- interrupts = ; +- reg = <7000 400>; ++ interrupts = <14 0>; ++ reg = <0x7000 0x400>; + device_type = "i2c"; + compatible = "tsi108-i2c"; + }; +@@ -59,20 +60,20 @@ + MDIO: mdio@6000 { + device_type = "mdio"; + compatible = "tsi108-mdio"; +- reg = <6000 50>; ++ reg = <0x6000 0x50>; + #address-cells = <1>; + #size-cells = <0>; + + phy8: ethernet-phy@8 { + interrupt-parent = <&mpic>; + interrupts = <2 1>; +- reg = <8>; ++ reg = <0x8>; + }; + + phy9: ethernet-phy@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@7808 { + device_type = "serial"; + compatible = "ns16550"; +- reg = <7808 200>; +- clock-frequency = <3f6b5a00>; +- interrupts = ; ++ reg = <0x7808 0x200>; ++ clock-frequency = <1064000000>; ++ interrupts = <12 0>; + interrupt-parent = <&mpic>; + }; + + serial@7c08 { + device_type = "serial"; + compatible = "ns16550"; +- reg = <7c08 200>; +- clock-frequency = <3f6b5a00>; +- interrupts = ; ++ 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 = ; ++ 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@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@0 { + device_type = "cpu"; +- reg = <0>; +- d-cache-line-size = ; +- i-cache-line-size = ; +- d-cache-size = ; +- i-cache-size = ; ++ 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@f0010100 { +@@ -42,21 +44,21 @@ + "fsl,pq2-localbus"; + #address-cells = <2>; + #size-cells = <1>; +- reg = ; ++ 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@0,0 { + compatible = "jedec-flash"; +- reg = <0 0 2000000>; ++ reg = <0x0 0x0 0x2000000>; + bank-width = <4>; + device-width = <1>; + }; + + board-control@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@f0010800 { + device_type = "pci"; +- reg = ; ++ 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 = ; +- interrupt-map-mask = ; ++ 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@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 = ; ++ reg = <0xf0000000 0x53000>; + + cpm@119c0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,mpc8272-cpm", "fsl,cpm2"; +- reg = <119c0 30>; ++ reg = <0x119c0 0x30>; + ranges; + + muram@0 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 0 10000>; ++ ranges = <0x0 0x0 0x10000>; + + data@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@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@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@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@0 { + interrupt-parent = <&PIC>; +- interrupts = <17 8>; +- reg = <0>; ++ interrupts = <23 8>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + + PHY1: ethernet-phy@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@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@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 = ; ++ 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@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@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@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@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@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@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@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@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@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <0 e0000000 00100000>; +- reg = ; // CCSRBAR 1M ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x100000>; // CCSRBAR 1M + bus-frequency = <0>; + + memory-controller@2000 { + compatible = "fsl,8540-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@0 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + phy3: ethernet-phy@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@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@e0008000 { + cell-index = <0>; +- interrupt-map-mask = ; ++ 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 = ; ++ 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@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@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <0 e0000000 00100000>; +- reg = ; // CCSRBAR 1M ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M + bus-frequency = <0>; + + memory-controller@2000 { + compatible = "fsl,8541-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@0 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@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@80000 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 80000 10000>; ++ ranges = <0x0 0x80000 0x10000>; + + data@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@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@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 = ; ++ reg = <0xe0008000 0x1000>; + compatible = "fsl,mpc8540-pci"; + device_type = "pci"; + + i8259@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@e0009000 { + cell-index = <1>; +- interrupt-map-mask = ; ++ 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 = ; ++ 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@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@e0000000 { +@@ -54,24 +54,24 @@ + #size-cells = <1>; + device_type = "soc"; + +- ranges = <00000000 e0000000 00100000>; +- reg = ; // CCSRBAR 1M ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M + bus-frequency = <0>; // Filled out by uboot. + + memory-controller@2000 { + compatible = "fsl,8544-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@0 { + interrupt-parent = <&mpic>; +- interrupts = ; +- reg = <0>; ++ interrupts = <10 1>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; +- interrupts = ; +- reg = <1>; ++ interrupts = <10 1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + }; + ++ dma@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@0 { ++ compatible = "fsl,mpc8544-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x0 0x80>; ++ cell-index = <0>; ++ interrupt-parent = <&mpic>; ++ interrupts = <20 2>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,mpc8544-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupt-parent = <&mpic>; ++ interrupts = <21 2>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,mpc8544-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupt-parent = <&mpic>; ++ interrupts = <22 2>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,mpc8544-dma-channel", ++ "fsl,eloplus-dma-channel"; ++ reg = <0x180 0x80>; ++ cell-index = <3>; ++ interrupt-parent = <&mpic>; ++ interrupts = <23 2>; ++ }; ++ }; ++ + enet0: ethernet@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@e0000 { //global utilities block + compatible = "fsl,mpc8548-guts"; +- reg = ; ++ 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 = ; ++ 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 = ; ++ reg = <0xe0008000 0x1000>; + }; + + pci1: pcie@e0009000 { +@@ -219,33 +260,33 @@ + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; +- reg = ; +- 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 = ; ++ 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@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 = ; +- 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 = ; ++ 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@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 = ; +- 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 = ; ++ 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@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@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@1e { + device_type = "isa"; + #interrupt-cells = <2>; + #size-cells = <1>; + #address-cells = <2>; +- reg = ; +- 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@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@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@0 { +- reg = <0>; ++ reg = <0x0>; + compatible = "pnpPNP,303"; + }; + + mouse@1 { +- reg = <1>; ++ reg = <0x1>; + compatible = "pnpPNP,f03"; + }; + }; + + rtc@70 { + compatible = "pnpPNP,b00"; +- reg = <1 70 2>; ++ reg = <0x1 0x70 0x2>; + }; + + gpio@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@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@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <00000000 e0000000 00100000>; +- reg = ; // CCSRBAR ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x1000>; // CCSRBAR + bus-frequency = <0>; + + memory-controller@2000 { + compatible = "fsl,8548-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@0 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + phy2: ethernet-phy@2 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <2>; ++ reg = <0x2>; + device_type = "ethernet-phy"; + }; + phy3: ethernet-phy@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@e0000 { //global utilities reg + compatible = "fsl,mpc8548-guts"; +- reg = ; ++ 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@e0008000 { + cell-index = <0>; +- interrupt-map-mask = ; ++ 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 = ; ++ reg = <0xe0008000 0x1000>; + compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci"; + device_type = "pci"; + + pci_bridge@1c { +- interrupt-map-mask = ; ++ 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 = ; ++ 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@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@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@70 { + compatible = "pnpPNP,b00"; +- reg = <1 70 2>; ++ reg = <0x1 0x70 0x2>; + }; + }; + }; +@@ -370,64 +371,64 @@ + + pci1: pci@e0009000 { + cell-index = <1>; +- interrupt-map-mask = ; ++ 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 = ; ++ reg = <0xe0009000 0x1000>; + compatible = "fsl,mpc8540-pci"; + device_type = "pci"; + }; + + pci2: pcie@e000a000 { + cell-index = <2>; +- interrupt-map-mask = ; ++ 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 = ; ++ reg = <0xe000a000 0x1000>; + compatible = "fsl,mpc8548-pcie"; + device_type = "pci"; + pcie@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@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@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <0 e0000000 00100000>; +- reg = ; // CCSRBAR 1M ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M + bus-frequency = <0>; + + memory-controller@2000 { + compatible = "fsl,8555-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@0 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@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@80000 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 80000 10000>; ++ ranges = <0x0 0x80000 0x10000>; + + data@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@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@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 = ; ++ reg = <0xe0008000 0x1000>; + compatible = "fsl,mpc8540-pci"; + device_type = "pci"; + + i8259@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@e0009000 { + cell-index = <1>; +- interrupt-map-mask = ; ++ 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 = ; ++ 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@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@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <0 e0000000 00100000>; +- reg = ; +- bus-frequency = <13ab6680>; ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x200>; ++ bus-frequency = <330000000>; + + memory-controller@2000 { + compatible = "fsl,8540-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@24520 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,gianfar-mdio"; +- reg = <24520 20>; ++ reg = <0x24520 0x20>; + + phy0: ethernet-phy@0 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; + interrupts = <5 1>; +- reg = <1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + phy2: ethernet-phy@2 { + interrupt-parent = <&mpic>; + interrupts = <7 1>; +- reg = <2>; ++ reg = <0x2>; + device_type = "ethernet-phy"; + }; + phy3: ethernet-phy@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@80000 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 80000 10000>; ++ ranges = <0x0 0x80000 0x10000>; + + data@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 = ; ++ reg = <0x919f0 0x10 0x915f0 0x10>; ++ clock-frequency = <165000000>; + }; + + cpmpic: pic@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 = ; +- clock-frequency = <3f940aa>; +- interrupt-map-mask = ; ++ 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@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@f8000000 { + device_type = "board-control"; +- reg = ; ++ reg = <0xf8000000 0x8000>; + }; + + soc8568@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <0 e0000000 00100000>; +- reg = ; ++ ranges = <0x0 0xe0000000 0x100000>; ++ reg = <0xe0000000 0x1000>; + bus-frequency = <0>; + + memory-controller@2000 { + compatible = "fsl,8568-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@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@7 { + interrupt-parent = <&mpic>; + interrupts = <1 1>; +- reg = <7>; ++ reg = <0x7>; + device_type = "ethernet-phy"; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; + interrupts = <2 1>; +- reg = <1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + phy2: ethernet-phy@2 { + interrupt-parent = <&mpic>; + interrupts = <1 1>; +- reg = <2>; ++ reg = <0x2>; + device_type = "ethernet-phy"; + }; + phy3: ethernet-phy@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@e0000 { //global utilities block + compatible = "fsl,mpc8548-guts"; +- reg = ; ++ 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@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@e0100 { +- reg = ; ++ reg = <0xe0100 0x100>; + device_type = "par_io"; + num-ports = <7>; + + pio1: ucc_pin@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@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 = ; ++ ranges = <0x0 0xe0080000 0x40000>; ++ reg = <0xe0080000 0x480>; + brg-frequency = <0>; +- bus-frequency = <179A7B00>; ++ bus-frequency = <396000000>; + + muram@10000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,qe-muram", "fsl,cpm-muram"; +- ranges = <0 00010000 0000c000>; ++ ranges = <0x0 0x10000 0x10000>; + + data-only@0 { + compatible = "fsl,qe-muram-data", + "fsl,cpm-muram-data"; +- reg = <0 c000>; ++ reg = <0x0 0x10000>; + }; + }; + + spi@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@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@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@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@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@07 { + interrupt-parent = <&mpic>; + interrupts = <1 1>; +- reg = <7>; ++ reg = <0x7>; + device_type = "ethernet-phy"; + }; + qe_phy1: ethernet-phy@01 { + interrupt-parent = <&mpic>; + interrupts = <2 1>; +- reg = <1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + qe_phy2: ethernet-phy@02 { + interrupt-parent = <&mpic>; + interrupts = <1 1>; +- reg = <2>; ++ reg = <0x2>; + device_type = "ethernet-phy"; + }; + qe_phy3: ethernet-phy@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@e0008000 { + cell-index = <0>; +- interrupt-map-mask = ; ++ 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 = ; ++ reg = <0xe0008000 0x1000>; + compatible = "fsl,mpc8540-pci"; + device_type = "pci"; + }; +@@ -435,39 +428,39 @@ + /* PCI Express */ + pci1: pcie@e000a000 { + cell-index = <2>; +- interrupt-map-mask = ; ++ 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 = ; ++ reg = <0xe000a000 0x1000>; + compatible = "fsl,mpc8548-pcie"; + device_type = "pci"; + pcie@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@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@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@ffe00000 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; +- ranges = <00000000 ffe00000 00100000>; +- reg = ; // 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@2000 { + compatible = "fsl,mpc8572-memory-controller"; +- reg = <2000 1000>; ++ reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + memory-controller@6000 { + compatible = "fsl,mpc8572-memory-controller"; +- reg = <6000 1000>; ++ reg = <0x6000 0x1000>; + interrupt-parent = <&mpic>; +- interrupts = <12 2>; ++ interrupts = <18 2>; + }; + + l2-cache-controller@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@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@0 { + interrupt-parent = <&mpic>; +- interrupts = ; +- reg = <0>; ++ interrupts = <10 1>; ++ reg = <0x0>; + }; + phy1: ethernet-phy@1 { + interrupt-parent = <&mpic>; +- interrupts = ; +- reg = <1>; ++ interrupts = <10 1>; ++ reg = <0x1>; + }; + phy2: ethernet-phy@2 { + interrupt-parent = <&mpic>; +- interrupts = ; +- reg = <2>; ++ interrupts = <10 1>; ++ reg = <0x2>; + }; + phy3: ethernet-phy@3 { + interrupt-parent = <&mpic>; +- interrupts = ; +- 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@e0000 { //global utilities block + compatible = "fsl,mpc8572-guts"; +- reg = ; ++ 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 = ; +- 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 = ; ++ 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@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@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@1e { + device_type = "isa"; + #interrupt-cells = <2>; + #size-cells = <1>; + #address-cells = <2>; +- reg = ; +- 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@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@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@0 { +- reg = <0>; ++ reg = <0x0>; + compatible = "pnpPNP,303"; + }; + + mouse@1 { +- reg = <1>; ++ reg = <0x1>; + compatible = "pnpPNP,f03"; + }; + }; + + rtc@70 { + compatible = "pnpPNP,b00"; +- reg = <1 70 2>; ++ reg = <0x1 0x70 0x2>; + }; + + gpio@400 { +- reg = <1 400 80>; ++ reg = <0x1 0x400 0x80>; + }; + }; + }; +@@ -449,33 +450,33 @@ + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; +- reg = ; +- 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 = ; ++ 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@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 = ; +- 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 = ; ++ 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@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@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 = ; // decrementer interrupt ++ interrupts = <15 2>; // decrementer interrupt + interrupt-parent = <&PIC>; + }; + }; + + memory { + device_type = "memory"; +- reg = <00000000 800000>; ++ reg = <0x0 0x800000>; + }; + + localbus@ff000100 { + compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus"; + #address-cells = <2>; + #size-cells = <1>; +- reg = ; ++ reg = <0xff000100 0x40>; + + ranges = < +- 1 0 ff080000 00008000 +- 5 0 ff0a0000 00008000 ++ 0x1 0x0 0xff080000 0x8000 ++ 0x5 0x0 0xff0a0000 0x8000 + >; + + board-control@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 = ; ++ ranges = <0x0 0xff000000 0x100000>; ++ reg = <0xff000000 0x200>; + bus-frequency = <0>; + + mdio@e00 { + compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio"; +- reg = ; ++ reg = <0xe00 0x188>; + #address-cells = <1>; + #size-cells = <0>; + PHY: ethernet-phy@f { +- reg = ; ++ reg = <0xf>; + device_type = "ethernet-phy"; + }; + }; +@@ -80,7 +82,7 @@ + device_type = "network"; + compatible = "fsl,mpc866-fec-enet", + "fsl,pq1-fec-enet"; +- reg = ; ++ reg = <0xe00 0x188>; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <3 1>; + interrupt-parent = <&PIC>; +@@ -91,7 +93,7 @@ + PIC: pic@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@2000 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 2000 2000>; ++ ranges = <0x0 0x2000 0x2000>; + + data@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 = ; ++ reg = <0xa80 0x10 0x3e80 0x40>; + interrupts = <4>; + interrupt-parent = <&CPM_PIC>; + fsl,cpm-brg = <1>; +- fsl,cpm-command = <0090>; ++ fsl,cpm-command = <0x90>; + }; + + serial@a90 { + device_type = "serial"; + compatible = "fsl,mpc866-smc-uart", + "fsl,cpm1-smc-uart"; +- reg = ; ++ reg = <0xa90 0x10 0x3f80 0x40>; + interrupts = <3>; + interrupt-parent = <&CPM_PIC>; + fsl,cpm-brg = <2>; +- fsl,cpm-command = <00d0>; ++ fsl,cpm-command = <0xd0>; + }; + + ethernet@a00 { + device_type = "network"; + compatible = "fsl,mpc866-scc-enet", + "fsl,cpm1-scc-enet"; +- reg = ; ++ 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@0 { + device_type = "cpu"; +- reg = <0>; +- d-cache-line-size = ; +- i-cache-line-size = ; +- d-cache-size = ; +- i-cache-size = ; ++ 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 = ; // decrementer interrupt ++ interrupts = <15 2>; // decrementer interrupt + interrupt-parent = <&PIC>; + }; + }; + + memory { + device_type = "memory"; +- reg = <0 0>; ++ reg = <0x0 0x0>; + }; + + localbus@ff000100 { + compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus"; + #address-cells = <2>; + #size-cells = <1>; +- reg = ; ++ 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@0,0 { + compatible = "jedec-flash"; +- reg = <0 0 800000>; ++ reg = <0x0 0x0 0x800000>; + bank-width = <4>; + device-width = <1>; + }; + + board-control@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 = ; ++ reg = <0xff000000 0x4000>; + + mdio@e00 { + compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio"; +- reg = ; ++ reg = <0xe00 0x188>; + #address-cells = <1>; + #size-cells = <0>; + + PHY0: ethernet-phy@0 { +- reg = <0>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + + PHY1: ethernet-phy@1 { +- reg = <1>; ++ reg = <0x1>; + device_type = "ethernet-phy"; + }; + + PHY2: ethernet-phy@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 = ; ++ 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@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 = ; ++ interrupts = <13 1>; + }; + + cpm@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@2000 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 2000 2000>; ++ ranges = <0x0 0x2000 0x2000>; + + data@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@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 = ; ++ reg = <0xa80 0x10 0x3e80 0x40>; + interrupts = <4>; + interrupt-parent = <&CPM_PIC>; + fsl,cpm-brg = <1>; +- fsl,cpm-command = <0090>; ++ fsl,cpm-command = <0x90>; + }; + + serial@a90 { + device_type = "serial"; + compatible = "fsl,mpc885-smc-uart", + "fsl,cpm1-smc-uart"; +- reg = ; ++ reg = <0xa90 0x10 0x3f80 0x40>; + interrupts = <3>; + interrupt-parent = <&CPM_PIC>; + fsl,cpm-brg = <2>; +- fsl,cpm-command = <00d0>; ++ fsl,cpm-command = <0xd0>; + }; + + ethernet@a40 { + device_type = "network"; + compatible = "fsl,mpc885-scc-enet", + "fsl,cpm1-scc-enet"; +- reg = ; ++ 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@0 { + device_type = "cpu"; +- reg = <0>; +- d-cache-line-size = ; +- i-cache-line-size = ; +- d-cache-size = ; +- i-cache-size = ; ++ 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@f0010100 { +@@ -41,67 +43,67 @@ + "fsl,pq2-localbus"; + #address-cells = <2>; + #size-cells = <1>; +- reg = ; ++ 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@0,0 { + compatible = "jedec-flash"; +- reg = <0 0 800000>; ++ reg = <0x0 0x0 0x800000>; + bank-width = <4>; + device-width = <1>; + }; + + bcsr@1,0 { +- reg = <1 0 20>; ++ reg = <0x1 0x0 0x20>; + compatible = "fsl,pq2fads-bcsr"; + }; + + PCI_PIC: pic@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@f0010800 { + device_type = "pci"; +- reg = ; ++ 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 = ; +- interrupt-map-mask = ; ++ 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@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 = ; ++ reg = <0xf0000000 0x53000>; + + cpm@119c0 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + compatible = "fsl,mpc8280-cpm", "fsl,cpm2"; +- reg = <119c0 30>; ++ reg = <0x119c0 0x30>; + ranges; + + muram@0 { + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 0 10000>; ++ ranges = <0x0 0x0 0x10000>; + + data@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@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@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@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@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 = ; ++ fsl,mdc-pin = <10>; + + PHY0: ethernet-phy@0 { + interrupt-parent = <&PIC>; +- interrupts = <19 2>; +- reg = <0>; ++ interrupts = <25 2>; ++ reg = <0x0>; + device_type = "ethernet-phy"; + }; + + PHY1: ethernet-phy@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 = ; +- fsl,cpm-command = <2e600000>; ++ interrupts = <11 8>; ++ fsl,cpm-command = <0x2e600000>; + }; + }; + + PIC: interrupt-controller@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@f1000000 { /* Marvell Discovery */ ++ system-controller@f1000000 { /* Marvell Discovery mv64360 */ + #address-cells = <1>; + #size-cells = <1>; + model = "mv64360"; /* Default */ +- compatible = "marvell,mv64x60"; +- clock-frequency = <7f28155>; /* 133.333333 MHz */ +- reg = ; +- virtual-reg = ; +- 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@a0000000 { + device_type = "rom"; + compatible = "direct-mapped"; +- reg = ; /* 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@1 { ++ compatible = "marvell,mv64360-mdio"; ++ PHY0: ethernet-phy@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@3 { ++ PHY1: ethernet-phy@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@2000 { +- reg = <2000 2000>; +- eth0 { ++ ethernet-group@2000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "marvell,mv64360-eth-group"; ++ reg = <0x2000 0x2000>; ++ ethernet@0 { + device_type = "network"; +- compatible = "marvell,mv64x60-eth"; +- block-index = <0>; +- interrupts = <20>; +- interrupt-parent = <&/mv64x60/pic>; +- phy = <&/mv64x60/mdio/ethernet-phy@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@1 { + device_type = "network"; +- compatible = "marvell,mv64x60-eth"; +- block-index = <1>; +- interrupts = <21>; +- interrupt-parent = <&/mv64x60/pic>; +- phy = <&/mv64x60/mdio/ethernet-phy@3>; ++ compatible = "marvell,mv64360-eth"; ++ reg = <1>; ++ interrupts = <33>; ++ interrupt-parent = <&PIC>; ++ phy = <&PHY1>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; + +- sdma@4000 { +- device_type = "dma"; +- compatible = "marvell,mv64x60-sdma"; +- reg = <4000 c18>; +- virtual-reg = ; +- interrupt-base = <0>; +- interrupts = <24>; +- interrupt-parent = <&/mv64x60/pic>; ++ SDMA0: sdma@4000 { ++ compatible = "marvell,mv64360-sdma"; ++ reg = <0x4000 0xc18>; ++ virtual-reg = <0xf1004000>; ++ interrupts = <36>; ++ interrupt-parent = <&PIC>; + }; + +- sdma@6000 { +- device_type = "dma"; +- compatible = "marvell,mv64x60-sdma"; +- reg = <6000 c18>; +- virtual-reg = ; +- interrupt-base = <0>; +- interrupts = <26>; +- interrupt-parent = <&/mv64x60/pic>; ++ SDMA1: sdma@6000 { ++ compatible = "marvell,mv64360-sdma"; ++ reg = <0x6000 0xc18>; ++ virtual-reg = <0xf1006000>; ++ interrupts = <38>; ++ interrupt-parent = <&PIC>; + }; + +- brg@b200 { +- compatible = "marvell,mv64x60-brg"; +- reg = ; ++ BRG0: brg@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@b208 { +- compatible = "marvell,mv64x60-brg"; +- reg = ; ++ BRG1: brg@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@f200 { +- reg = ; ++ CUNIT: cunit@f200 { ++ reg = <0xf200 0x200>; + }; + +- mpscrouting@b400 { +- reg = ; ++ MPSCROUTING: mpscrouting@b400 { ++ reg = <0xb400 0xc>; + }; + +- mpscintr@b800 { +- reg = ; +- virtual-reg = ; ++ MPSCINTR: mpscintr@b800 { ++ reg = <0xb800 0x100>; ++ virtual-reg = <0xf100b800>; + }; + +- mpsc@8000 { ++ MPSC0: mpsc@8000 { + device_type = "serial"; +- compatible = "marvell,mpsc"; +- reg = <8000 38>; +- virtual-reg = ; +- sdma = <&/mv64x60/sdma@4000>; +- brg = <&/mv64x60/brg@b200>; +- cunit = <&/mv64x60/cunit@f200>; +- mpscrouting = <&/mv64x60/mpscrouting@b400>; +- mpscintr = <&/mv64x60/mpscintr@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@9000 { ++ MPSC1: mpsc@9000 { + device_type = "serial"; +- compatible = "marvell,mpsc"; +- reg = <9000 38>; +- virtual-reg = ; +- sdma = <&/mv64x60/sdma@6000>; +- brg = <&/mv64x60/brg@b208>; +- cunit = <&/mv64x60/cunit@f200>; +- mpscrouting = <&/mv64x60/mpscrouting@b400>; +- mpscintr = <&/mv64x60/mpscintr@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@b410 { /* watchdog timer */ +- compatible = "marvell,mv64x60-wdt"; +- reg = ; +- timeout = ; /* wdt timeout in seconds */ ++ compatible = "marvell,mv64360-wdt"; ++ reg = <0xb410 0x8>; + }; + + i2c@c000 { + device_type = "i2c"; +- compatible = "marvell,mv64x60-i2c"; +- reg = ; +- virtual-reg = ; +- 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@f000 { +- compatible = "marvell,mv64x60-mpp"; +- reg = ; ++ compatible = "marvell,mv64360-mpp"; ++ reg = <0xf000 0x10>; + }; + + gpp@f100 { +- compatible = "marvell,mv64x60-gpp"; +- reg = ; ++ compatible = "marvell,mv64360-gpp"; ++ reg = <0xf100 0x20>; + }; + + pci@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 = ; ++ 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@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@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@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@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@f1000000/mpsc@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@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@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@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@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@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@0,0 { ++ compatible = "cfi-flash"; ++ reg = <0 0 0x01000000>; ++ bank-width = <2>; ++ device-width = <2>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ partition@0 { ++ label = "dtb"; ++ reg = <0x00000000 0x00100000>; ++ read-only; ++ }; ++ partition@300000 { ++ label = "kernel"; ++ reg = <0x00100000 0x00400000>; ++ read-only; ++ }; ++ partition@400000 { ++ label = "fs"; ++ reg = <0x00500000 0x00a00000>; ++ }; ++ partition@700000 { ++ label = "firmware"; ++ reg = <0x00f00000 0x00100000>; ++ read-only; ++ }; ++ }; ++ ++ epld@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@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@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ dfsrr; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <43 2>; ++ interrupt-parent = <&mpic>; ++ dfsrr; ++ }; ++ ++ mdio@24520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x24520 0x20>; ++ ++ phy0: ethernet-phy@1f { ++ interrupt-parent = <&mpic>; ++ interrupts = <10 1>; ++ reg = <0x1f>; ++ device_type = "ethernet-phy"; ++ }; ++ phy1: ethernet-phy@0 { ++ interrupt-parent = <&mpic>; ++ interrupts = <10 1>; ++ reg = <0>; ++ device_type = "ethernet-phy"; ++ }; ++ phy2: ethernet-phy@1 { ++ interrupt-parent = <&mpic>; ++ interrupts = <10 1>; ++ reg = <1>; ++ device_type = "ethernet-phy"; ++ }; ++ phy3: ethernet-phy@2 { ++ interrupt-parent = <&mpic>; ++ interrupts = <10 1>; ++ reg = <2>; ++ device_type = "ethernet-phy"; ++ }; ++ }; ++ ++ enet0: ethernet@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@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@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@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@4500 { ++ cell-index = <0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0>; ++ interrupts = <42 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ serial1: serial@4600 { ++ cell-index = <1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <28 2>; ++ interrupt-parent = <&mpic>; ++ }; ++ ++ mpic: pic@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@e0000 { ++ compatible = "fsl,mpc8641-guts"; ++ reg = <0xe0000 0x1000>; ++ fsl,has-rstcr; ++ }; ++ }; ++ ++ pci0: pcie@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@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@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@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@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@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@40000b50 { ++ compatible = "ibm,tah-440gx", "ibm,tah"; ++ reg = <40000b50 30>; ++ }; ++ ++ TAH1: emac-tah@40000d50 { ++ compatible = "ibm,tah-440gx", "ibm,tah"; ++ reg = <40000d50 30>; ++ }; + + EMAC0: ethernet@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@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@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@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@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@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 ++ * ++ * 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@0>; ++ ++ aliases { ++ ethernet0 = &EMAC0; ++ ethernet1 = &EMAC1; ++ serial0 = &UART0; ++ serial1 = &UART1; ++ serial2 = &UART2; ++ serial3 = &UART3; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@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 = ; ++ }; ++ ++ 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@ef600300 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; /* Filled in by zImage */ ++ current-speed = <1c200>; ++ interrupt-parent = <&UIC0>; ++ interrupts = <0 4>; ++ }; ++ ++ UART1: serial@ef600400 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; ++ current-speed = <0>; ++ interrupt-parent = <&UIC0>; ++ interrupts = <1 4>; ++ }; ++ ++ UART2: serial@ef600500 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; ++ current-speed = <0>; ++ interrupt-parent = <&UIC0>; ++ interrupts = <3 4>; ++ status = "disabled"; ++ }; ++ ++ UART3: serial@ef600600 { ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = ; ++ virtual-reg = ; ++ clock-frequency = <0>; ++ current-speed = <0>; ++ interrupt-parent = <&UIC0>; ++ interrupts = <4 4>; ++ status = "disabled"; ++ }; ++ ++ IIC0: i2c@ef600700 { ++ compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic"; ++ reg = ; ++ interrupt-parent = <&UIC0>; ++ interrupts = <2 4>; ++ }; ++ ++ IIC1: i2c@ef600800 { ++ compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic"; ++ reg = ; ++ interrupt-parent = <&UIC0>; ++ interrupts = <7 4>; ++ }; ++ ++ spi@ef600900 { ++ compatible = "amcc,spi-440ep"; ++ reg = ; ++ interrupts = <8 4>; ++ interrupt-parent = <&UIC0>; ++ }; ++ ++ ZMII0: emac-zmii@ef600d00 { ++ compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii"; ++ reg = ; ++ }; ++ ++ EMAC0: ethernet@ef600e00 { ++ device_type = "network"; ++ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac"; ++ interrupt-parent = <&UIC1>; ++ interrupts = <1c 4 1d 4>; ++ reg = ; ++ 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@ef600f00 { ++ device_type = "network"; ++ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac"; ++ interrupt-parent = <&UIC1>; ++ interrupts = <1e 4 1f 4>; ++ reg = ; ++ 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@ef601000 { ++ compatible = "ohci-be"; ++ reg = ; ++ interrupts = <8 4 9 4>; ++ interrupt-parent = < &UIC1 >; ++ }; ++ }; ++ ++ PCI0: pci@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 = ; ++ 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@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@80000000"); ++ devp = find_node_by_compatible(NULL, "marvell,mv64360-pci"); + if (devp == NULL) +- fatal("Error: Missing /mv64x60/pci@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@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@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 ++ * Grant Likely ++ * ++ * 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@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 + #include +-#else +-#include + #endif + + #include +@@ -46,6 +44,9 @@ + #include + #include + #endif ++#ifdef CONFIG_PPC_ISERIES ++#include ++#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 + #include + #include ++#include + + #include + #include +@@ -15,7 +16,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + +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 + * MontaVista Software, Inc (c) 2007 + * +- * Based on cpu_setup_6xx code by ++ * Based on cpu_setup_6xx code by + * Benjamin Herrenschmidt + * + * 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 + + _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 + #include + #include ++#include + + #include + #include + #include + #include +-#include ++#include + #include + #include + #include +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 + #include ++#include + #include +-#include ++#include + #include + #include + +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@h ++ andis. r12,r12,DBCR0_IDM@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@ha + tophys(r11,r11) + addi r11,r11,global_dbcr0@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@h ++ andis. r10,r0,DBCR0_IDM@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@h ++ andis. r10,r0,DBCR0_IDM@h + bnel- load_dbcr0 + #endif + +@@ -879,6 +885,12 @@ load_dbcr0: + mfspr r10,SPRN_DBCR0 + lis r11,global_dbcr0@ha + addi r11,r11,global_dbcr0@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 + #include + #include ++#include ++#include + + /* + * 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@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 + #include + #include ++#include + + /* 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@ha; /* exception frame marker */ \ ++ addi r10,r10,STACK_FRAME_REGS_MARKER@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@h +- stw r3,_MSR(r1) /* enable use of AltiVec after return */ +- lis r3,87f@h +- ori r3,r3,87f@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@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 + #include + #include +- +-#define DO_SOFT_DISABLE ++#include + + /* + * 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@h; \ +- ori r10,r10,Debug@l; \ ++ lis r10,DebugDebug@h; \ ++ ori r10,r10,DebugDebug@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@h; \ +- ori r10,r10,Debug@l; \ ++ lis r10,DebugCrit@h; \ ++ ori r10,r10,DebugCrit@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@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@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@ha ++ la r3,kernstart_addr@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@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 + #include + #include ++#include + #include +-#include ++#include + + 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@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 + #include + #include + +-#include +-#include +-#include + #include +-#include + #include +-#include +- + + /* 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 + + #include +-#include + #include + #include + #include +@@ -45,10 +44,6 @@ + #include + #include + +-#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 + #include + #include ++#include + + #include + #include +-#include + #include + #include + #include +@@ -51,7 +51,9 @@ + #include + #include + #include ++#include + #include ++#include + + #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 + #include + #include ++#include + + #include + #include + #include +-#include + #include + #include + #include +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -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 +- * +- * This program is free software; you can redistribute it and/or +- * 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 +- * 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 +-#include +-#include +- +-#include +-#include +-#include +- +-/* +- * 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 + #include + #include ++#include + #include + #include + #include +@@ -56,7 +57,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -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 + #include + #include +-#if defined(CONFIG_IDE) || defined(CONFIG_IDE_MODULE) +-#include +-#endif + #include + #include + #include +@@ -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 + #include + #include ++#include ++#include + #include + #include + #include +@@ -55,7 +57,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -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 ++#include ++#include ++ ++/* ++ * 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 + #include + #include +-#include + #include + #include + #include +@@ -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 + + #include +-#include + #include + #include + #include +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 + #include + #include ++#include + + #include + #include + #include + #include + #include +-#include ++#include + #include + #include + #include +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 : ""); + 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 : ""); + 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 + #define PROVIDE32(x) PROVIDE(__unused__##x) + #else +-#define PAGE_SIZE 4096 +-#define KERNELBASE CONFIG_KERNEL_START + #define PROVIDE32(x) PROVIDE(x) + #endif ++#include + #include + #include + +@@ -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 + #include + #include +-#include + #include + #include + ++#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@ha + addi r9,r9,mmu_hash_lock@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 + #include + #include ++#include + + #include + #include +@@ -41,7 +42,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -41,7 +42,6 @@ + #include + #include + #include +-#include + #include + + #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 + #include + #include ++#include + + #include + #include + #include +-#include + #include + #include + #include +@@ -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 +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef CONFIG_PPC32 +-#include "mmu_decl.h" /* for __max_low_memory */ +-#endif +- +-#undef DEBUG +- +-#ifdef DEBUG +-#include +-#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 + #include + #include ++#include + + #include + #include +@@ -42,9 +43,9 @@ + #include + #include + #include +-#include + #include + #include ++#include + + #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 + #include + #include ++#include ++#include + #include +-#include ++#include + #include + #include + +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 + #include ++#include + #include + + #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 + #include + #include ++#include + + #include + #include + #include +-#include + + #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 ++ + #include + #include + #include + #include + #include +-#include ++#include + #include + #include + #include +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 + #include + #include ++#include + + 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 ++ * Copyright 2007-2008 DENX Software Engineering, Stefan Roese + * + * Based on the Walnut code by + * Josh Boyer +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + 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 + #include + #include ++#include + + 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 + #include + #include ++#include + + 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 + #include + #include ++#include + + 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 + #include + #include +- +-#include "44x.h" ++#include + + 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 ++ * ++ * Based on the Katmai code by ++ * Benjamin Herrenschmidt ++ * Copyright 2007 IBM Corp. ++ * Josh Boyer ++ * 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 ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include +- +-#include "44x.h" ++#include + + 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 ++ * ++ * 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 ++#include ++#include ++ ++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 + #include + #include +- +-#include "44x.h" ++#include + + 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@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 + #include + #include +-#include "44x.h" ++#include + + 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 + #include + +-#include "44x.h" ++#include + + 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 + #include + #include +- +-#include "44x.h" ++#include + + 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 + #include + #include ++#include + + #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 + #include + #include +- +-#include "44x.h" +- ++#include + + 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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++ ++#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 + #include + #include ++#include + + #include + #include +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ ++#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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 ++ ++#include ++#include ++#include ++ ++#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 ++#include ++ ++#include ++#include ++#include ++ ++#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 , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* 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< 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@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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + * 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 +-#include +-#include ++ + #include + #include +-#include ++#include + #include + ++#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 + +-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 + +-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 ++#include ++ ++/* 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 + #include + #include ++#include + + #include + #include + #include + #include + #include +-#include + #include + #include + +@@ -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 ++#include ++#include ++ ++#include ++#include ++ ++#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 + + #include +-#include + #include + #include + #include +@@ -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 + + #include +-#include + #include + #include + #include +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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#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 +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#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 +- +-#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 +-#include +-#include +-#include +-#include +- +-#include +- +-#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 +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#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 +-#include +-#include +-#include +-#include +- +-#include +- +-#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 , 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +- +-#include +-#include +-#include +- +-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 +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +-#include +-#include +-#include +- +-#include +-#include +- +-/* 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< 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@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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#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 +- +-#include +-#include +-#include +- +-#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 +-#include +- +-#include +-#include +-#include +- +-#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 + #include + #include +-#include + #include + #include + #include ++#include + + #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 + #include + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -57,7 +58,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include + #include +@@ -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 + * +@@ -27,7 +27,6 @@ + #include + #include + +- + #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 + #include + +-#include + #include + #include + +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 +-#include + #include + + /* +@@ -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 + #include + #include ++#include + + #include + #include +@@ -74,7 +75,6 @@ + #include + #include + #include +-#include + #include + + #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 ++#include + + #include +-#include ++#include + #include + #include + #include +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 + #include + #include ++#include + + #include +-#include ++#include + #include + #include + +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 + #include + #include ++#include ++#include + +-#include ++#include + + #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 + #include + #include ++#include + + #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 + = 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 + #include + +-#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 + #include + +-#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 + #include + #include + +-#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 : ""); + 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 + #include +@@ -40,12 +41,8 @@ + #include + + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 > /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 + #include + +-#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 + #include + #include +@@ -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 + #include +@@ -51,12 +50,6 @@ + #include "plpar_wrappers.h" + #include "pseries.h" + +-#ifdef DEBUG +-#include +-#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 + #include +@@ -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 + +-#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 + #include + #include ++#include + #include + #include + #include +@@ -44,7 +45,6 @@ + #include + #include + #include +-#include + #include + + #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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++ ++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@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 ++ * ++ * L2 cache routines cloned from arch/ppc/syslib/ibm440gx_common.c which is: ++ * Eugene Surovegin or ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++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 + + #include ++#include + #include + #include + +@@ -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 + #include +-#include + #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: + +-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@h +- stw r3,_MSR(r1) /* enable use of AltiVec after return */ +- lis r3,87f@h +- ori r3,r3,87f@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<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 + #include + #include +-#include + #include + #include + +@@ -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 +- * +- * This program is free software; you can redistribute it and/or +- * 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 +- * 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 +-#include +-#include +-#include +-#include +- +-/* +- * 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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + #include +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 + #include +-#include + #include + #include + #include +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 + #include +-#include + #include + #include + #include +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 + +-#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 + #include + #include +-#include + #include + #include + +@@ -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 + #include + #include +-#include + #include + #include + #include +@@ -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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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@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 +- +-/* 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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-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@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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + #include + +@@ -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 +- * 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 +- +-#include +-#include +-#include +-#include +- +-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@mvista.com) +- */ +-#ifdef __KERNEL__ +-#ifndef __MACH_ADS8260_DEFS +-#define __MACH_ADS8260_DEFS +- +- +-#include +- +-#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 +- * +- * 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 + #include + #include +-#include + #include + #include + +@@ -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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + +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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include + + #include + #include +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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + + //#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 + #include + #include +-#include + #include + #include + +@@ -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 +- ++ 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@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 ++#include ++ ++/* 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 + + #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 + + #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@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 ++#include ++#include ++ ++#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@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 ++#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 + #include +-#include + + #include + #include +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 + #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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include ++#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 ++#include ++#include ++ ++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 + #include + #include ++#include ++#include + #include + #include + #include +@@ -44,6 +46,7 @@ + #include + #include + #include ++#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 + #include + #include ++#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 + #include + #include +- ++#include + #include + #include + #include + #include ++#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 +-#include +-#include +- +-#include +- +-/* +- * 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 + #include + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#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 + #include + #include ++#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 + #include + #include +- + #include ++#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 + #include + #include +- ++#include + #include + #include + #include +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + /* 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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + #include + #include ++#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 + #include + #include +- + #include + #include + #include + #include ++#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 + #include + #include ++#include ++#include ++#include ++#include + #include + #include ++#include ++#include + + /* 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 + #include + #include ++#include + #include + #include + #include +@@ -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 ++#include ++#include ++#include ++#include ++ ++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 ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + #include + #include + #include + #include ++#include + + /* 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 + #elif defined(CONFIG_SH_7722_SOLUTION_ENGINE) + #include ++#elif defined(CONFIG_SH_7721_SOLUTION_ENGINE) ++#include + #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 ++#include ++#include ++#include ++ ++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 ++#include ++#include ++#include ++#include ++#include ++ ++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 +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-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 +- * 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 + #include + #include ++#include ++#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + #include + #include +@@ -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,@r4 +-#elif defined(CONFIG_CPU_SH4) ++#if defined(CONFIG_CPU_SH4) + movca.l r0,@r4 + mov r4,r1 ++#else ++ mov.l r0,@r4 + #endif + add #32,r4 + mov.l r0,@-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,@r10 +-#elif defined(CONFIG_CPU_SH4) ++#if defined(CONFIG_CPU_SH4) + movca.l r0,@r10 + mov r10,r0 ++#else ++ mov.l r0,@r10 + #endif + add #32,r10 + mov.l r7,@-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 +- 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@davemloft.net) +- * +- * Based upon preliminary work which is: +- * +- * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) +- */ +- +-#include /* 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@caip.rutgers.edu) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +-#include +-#include +- +-#include +- +-/* +- * 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 +- * 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 + #include +-#include + #include + #include + #include /* 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 + #include + #include +-#include + #include + #include + #include + #include +-#include + #include + #include + #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@caip.rutgers.edu) +- * +- * Based upon preliminary work which is: +- * +- * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) +- */ +- +-#include +- +- .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@nuclecu.unam.mx) +- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) +- */ +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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@nuclecu.unam.mx) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-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@caip.rutgers.edu) +- * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) +- * +- * Based upon preliminary work which is: +- * +- * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) +- * +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include +-#ifndef KERNEL_DS +-#include +-#endif +- +-#include +-#include +-#include +-#include /* for gethostid() */ +-#include +-#include +- +-/* For the nfs mount emulation */ +-#include +-#include +-#include +-#include +-#include +- +-/* for sunos_select */ +-#include +-#include +- +-/* 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 +- 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 +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-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 ++ * Copyright (C) 2007, 2008 David S. Miller + */ + #include + #include +-#include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + +@@ -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 + #include + #include +-#include + #include ++#include + + #include + #include +@@ -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 +-#include +-#include +- +-/* +- * 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 + #include +-#include + #include + #include + #include +@@ -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 + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include ++#include + + #include + #include +@@ -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 + #include + #include +-#include + #include + #include + #include + #include + #include +-#include + #include + #include + #include +@@ -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@nuclecu.unam.mx) +- * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) +- */ +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 + #include + #include +-#include + #include + #include + +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@caip.rutgers.edu) +- * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) +- * +- * Based upon preliminary work which is: +- * +- * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include /* for gethostid() */ +-#include +-#include +-#include +- +-/* For the nfs mount emulation */ +-#include +-#include +-#include +-#include +-#include +- +-/* for sunos_select */ +-#include +-#include +- +-/* For SOCKET_I */ +-#include +-#include +- +-#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 + #include + #include ++#include ++#include + + #include + #include +@@ -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@sunsite.mff.cuni.cz) +- */ +- +-/* #define DEBUG_SOLARIS */ +-#define DEBUG_SOLARIS_KMALLOC +- +-#ifndef __ASSEMBLY__ +- +-#include +- +-/* 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@sunsite.mff.cuni.cz) +- * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) +- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) +- */ +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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@sunsite.mff.cuni.cz) +- * +- * 1999-08-19 Implemented solaris F_FREESP (truncate) +- * fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#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@sunsite.mff.cuni.cz) +- * Copyright (C) 1997,1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) +- * +- * Streams & timod emulation based on code +- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) +- * +- * 1999-08-19 Implemented solaris 'm' (mag tape) and +- * 'O' (openprom) ioctls, by Jason Rappleye +- * (rappleye@ccr.buffalo.edu) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +-#include +- +-#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@sunsite.mff.cuni.cz) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#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@sunsite.mff.cuni.cz) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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@ultra.linux.cz), Patrik Rak (prak3264@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@sunsite.mff.cuni.cz) +- */ +- +-#include +-#include +- +-#include +-#include +-#include +- +-#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@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@ultra.linux.cz) +- * +- * 1999-08-19 Fixed socketpair code +- * Jason Rappleye (rappleye@ccr.buffalo.edu) +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#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@sunsite.mff.cuni.cz) +- * Copyright (C) 1997, 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) +- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include +-#include +- +-#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@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@sunsite.mff.cuni.cz) +- * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) +- */ +- +-#include +- +-/* 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@ss1000.ms.mff.cuni.cz) +- * +- * Streams & timod emulation based on code +- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) +- * +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include +-#include +- +-#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 +-#include +-#include +- +-#include +- +-/* +- * 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 +- * 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 + + #include +-#include + #include + + /* +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 + #include + #include +-#include + #include + #include + +@@ -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 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 + #include + #include ++#include + #include + #include + +@@ -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 + #include ++#include + #include + #include + #include +@@ -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> 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 + #include + #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 + #include + #include +-#include + #include + #include +-#include + #include +-#include +-#include + #include +-#include +-#include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include + #include + #include + #include +-#include + #include +-#include +-#include +-#include +-#include + #include + #include + #include + #include +-#include +-#include + #include + #include + #include + #include +-#include + #include +-#include +- +-#include +-#include + #include ++#include + + #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 + #include + #include ++#include ++ ++#ifdef CONFIG_X86_LOCAL_APIC ++# include ++#endif + + static int __initdata acpi_force = 0; + +@@ -52,9 +57,7 @@ EXPORT_SYMBOL(acpi_disabled); + #ifdef CONFIG_X86_64 + + #include +- +-static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } +- ++#include + + #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 + * - 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 + * - 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 ++#include ++#include ++#include ++ ++ .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 ++ ++/* 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 + #include + +-#include ++#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 ++ ++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 +- */ +- +-#include +-#include +-#include +-#include +- +-#include +- +-/* 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 + #include + +-# +-# 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 , 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 + + # Copyright 2003 Pavel Machek , 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 + #include + #include ++#include ++#include + + #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 + + 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 ++ */ ++ 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 + #include + #include +-#include + #include + #include + #include + #include + #include + ++#include ++#include ++ + 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 + #include + #include +-#include "sigframe_32.h" ++#include "sigframe.h" + #include + #include + #include +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 + #include + #include ++#include + + 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 + #include + #include +-#include + ++#include + #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 + #include + #include ++ + #include + #include + #include + #include ++ + #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 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>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 + #include + #include +-#include + #include + #include + #include +@@ -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: [()] */ +-/* This table only is used unless init_() below doesn't set it; */ +-/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */ ++/* ++ * Naming convention should be: [()] ++ * This table only is used unless init_() 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 + + /* + * These flag bits must match the definitions in . +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 + #include + +-#include ++#include + #include + #include + + #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 + #include + +-#include ++#include + #include + #include + +@@ -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 + #include + +-#include ++#include + #include + #include + + #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 + #include + +-#include ++#include + #include + #include + + #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 + #include + +-#include ++#include + #include + #include + + #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 + #include + #include ++#include + #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 +-#include +-#include +-#include +- +-#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 + #include + #include +-#include + #include + #include + + /* + * 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 + #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 + #include + +-#ifdef CONFIG_X86_32 + #include +-#else +-#include +-#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 + #include + #include ++#include + + 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 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 + #include + #include ++#include + #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 + #include + #include ++#include + + #include + #include +@@ -24,20 +25,20 @@ + #include + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 SuSE ++ * Copyright (C) 2007 Eric Biederman ++ */ ++ ++#include ++#include ++ ++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 + #include + #include ++#include + + 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 +-#include + #include + #include + #include + +-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 , May 2000 + */ +- +-#include + #include + #include ++#include ++ ++#include + #include +-#include + #include +-#include +-#include +-#include + #include ++#include ++#include ++#include + + #ifdef CONFIG_X86_64 +- +-#include +-#include +- ++# include ++# include + #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 + #include + #include +-#include + #include + #include + #include + #include + #include + ++#include ++#include ++ + 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 ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_X86_32 ++#include ++/* ++ * 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 ++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 ++ * 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 ++ * Updated by: Tom Rini ++ * Updated by: Jason Wessel ++ * Modified for 386 by Jim Kingdon, Cygnus Support. ++ * Origianl kgdb, compatibility with 2.1.xx kernel by ++ * David Grothe ++ * Integrated into 2.2.5 kernel by Tigran Aivazian ++ * X86_64 changes from Andi Kleen's patch merged by Jim Houston ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++/* ++ * 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 + #include + +-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@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; ipos[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 ++ * (c) 1998, 1999, 2000 Ingo Molnar ++ * (c) 2008 Alexey Starikovskiy ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#ifdef CONFIG_X86_32 ++#include ++#include ++#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 +- * (c) 1998, 1999, 2000 Ingo Molnar +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-/* 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 +- */ +- 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<= 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 +- * (c) 1998, 1999, 2000 Ingo Molnar +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* 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< + #include + #include ++#include + + #include + #include ++#include + + #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 + #include + ++#include ++ + 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 + #include + #include ++#include + + #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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++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 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 +-#include +-#include +-#include +-#include +-#include +- +-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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-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 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++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 +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-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 ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + + #include + #include +@@ -45,7 +46,6 @@ + #include + #include + #include +-#include + #ifdef CONFIG_MATH_EMULATION + #include + #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 + #include + #include ++#include + + #include + #include +@@ -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 +-#include + #include + #include + #include +@@ -9,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -16,7 +16,6 @@ + # include + # include + # include +-# include + #else + # include + #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 + #include + #include ++#include ++#include + + /* + * 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 + #include + #include ++#include ++#include + + /* + * 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 + + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + #include + #include + #include +@@ -23,6 +24,7 @@ + #include + #include + #include ++#include + + #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 + #include + #include ++#include + #include + #include + #include +@@ -62,8 +63,9 @@ + #include + #include + #include +-#include ++#include + #include ++#include + + /* 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 + #include + #include ++#include + #include + #include + #include +@@ -58,7 +59,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -66,7 +66,9 @@ + #include + #include + #include ++#include + ++#include + #ifdef CONFIG_PARAVIRT + #include + #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 + +-#include +-#include +-#include ++#include ++#include ++#include + #include ++#include + #include ++#include ++#include + #include ++#include + #include +-#include +-#include +-#include +-#include +-#include + #include +-#include ++#include ++#include ++ + #include + #include + #include + #include + #include +-#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 + #include + #include ++#include + #include + #include + #include + #include + #include + #include +- +-/* #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 ++ * (c) 1998-99, 2000 Ingo Molnar ++ * (c) 2002,2003 Andi Kleen, SuSE Labs. ++ * ++ * i386 and x86_64 integration by Glauber Costa ++ * ++ * This code is released under the GNU General Public License version 2 or ++ * later. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++/* ++ * 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 +- * (c) 1998-99, 2000 Ingo Molnar +- * +- * This code is released under the GNU General Public License version 2 or +- * later. +- */ +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-/* +- * 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 /* 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 +- */ +- +-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 +- * (c) 1998-99, 2000 Ingo Molnar +- * (c) 2002,2003 Andi Kleen, SuSE Labs. +- * +- * This code is released under the GNU General Public License version 2 or +- * later. +- */ +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* +- * 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 +- * +- * 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 +- * 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 ++ * (c) 1998, 1999, 2000 Ingo Molnar ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * 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 +- * (c) 1998, 1999, 2000 Ingo Molnar +- * +- * 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 +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-/* 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 +- * (c) 1998, 1999, 2000 Ingo Molnar +- * 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 +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* 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 ++#include ++ ++#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 +-#include + +-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 + #include + #include ++#include + #include + + 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 + #include +@@ -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 + + #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 + }; +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 + #include ++#include ++ + #include + #include + +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 ++#include ++#include ++ ++#include ++ ++DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ++ ____cacheline_aligned = { &init_mm, 0, }; ++ ++/* must come after the send_IPI functions above for inlining */ ++#include ++ ++/* ++ * 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 ++ */ ++ ++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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++/* ++ * 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 ++ * ++ * 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 ++ ++#include ++ ++/* 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",@progbits ++.section ".cpuinit.data","aw",@progbits + #else + .section .rodata,"a",@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 + #include + +-/* 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + #include ++#include ++#include + #include ++#include ++#include + #include ++#include ++#include + #include +-#include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include + #include ++#include ++#include + + #ifdef CONFIG_EISA + #include +@@ -43,21 +45,18 @@ + #include + #endif + ++#include ++#include + #include +-#include +-#include +-#include + #include ++#include ++#include ++#include + #include + #include + #include +-#include + #include +-#include +-#include +-#include +- +-#include ++#include + + #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 + #include + ++#include ++ + #if defined(CONFIG_EDAC) + #include + #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 + #include + #include ++#include + + 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 , + * Shai Fultheim ++ * Paravirt ops integration: Glauber de Oliveira Costa , ++ * Ravikiran Thirumalai + */ + + #include +@@ -15,38 +17,137 @@ + #include + #include + #include ++#include + +-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 + #include + +-#include + #include + #include + #include +@@ -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 + + #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 +-#include +-#include +-#include +-#include +- +-#include +-#include +- +- + /* + * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ + 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 + + #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 + +-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 + */ + 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 + #include + #include +@@ -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 + + 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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#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 "); +-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@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@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@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 + #include + #include ++#include + + /* 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@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 + #include + #include +-#include ++#include + + 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 ++ * ++ * This program is free software; 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 ++#include ++#include ++#include ++ ++#include ++ ++/* ++ * 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 "); ++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 + #include + +-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 + #include + #include +- +-enum ioremap_mode { +- IOR_MODE_UNCACHED, +- IOR_MODE_CACHED, +-}; ++#include + + #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 + #include + #include ++#include ++#include + + #include + #include +@@ -17,6 +19,7 @@ + #include + #include + #include ++#include + + /* + * 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 ++ * Suresh B Siddha ++ * ++ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 ++#include ++#include ++#include ++ ++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 + #include + #include +@@ -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 + #include + #include ++#include + + 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 + #include + #include +- +-/* 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 + #include + #include +- ++ + 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 + #include + #include +- ++ + #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 + #include + #include +- ++ + #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; iresource[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 + #include + #include ++#include ++ ++#include + + #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 + * +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 + #include + #include ++#include + + #include + #include +@@ -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 , XenSource Inc, 2007 +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#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 +-#include +-#include +-#include +-#include +- +-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< ++ * 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++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 + #include + ++#include + #include + #include + +@@ -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 ++#include ++#include + + /* 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 +- * +- * 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 +- * Chris Zankel +- * Marc Gauthier +- * Kevin Chea +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-/* +- * 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 +- * 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 + #include + #include +-#include + #ifdef CONFIG_BLK_DEV_FD + #include + #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 + #include + #include ++#include /* 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: +- ++ 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: +- . ++ 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: +- ++ 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: +- ++ 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: +- ++ 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: +- ++ . + +-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: +- ++ ++ ++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 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 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 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: ++ ++ ++ ++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: ++ ++ ++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: ++ ++ + 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: + + +-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: +- +- +- +-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: +- +- + 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 . See + +-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: ++ ++ ++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: ++ ++ ++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: ++ ++ ++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: +- ++ + +-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: ++ ++ ++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 "); + 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 ++ */ ++ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 +- * +- * Copyright (c) Jean-Luc Cooke +- * Copyright (c) Andrew McDonald +- * Copyright (c) 2003 Kyle McMartin +- * +- * This program is free software; you can redistribute 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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-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 ++ * ++ * Copyright (c) Jean-Luc Cooke ++ * Copyright (c) Andrew McDonald ++ * Copyright (c) 2003 Kyle McMartin ++ * ++ * This program is free software; you can redistribute 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++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 + * Copyright (C) 2001, 2002 Paul Diefenbaugh ++ * Copyright (c) 2008 Intel Corporation ++ * Author: Matthew Wilcox + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * +@@ -37,15 +39,18 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +- + #include + #include + #include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include + + #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 + #include + #include +-#include + #include + #include + #include +@@ -62,7 +61,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -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@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 + #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 + #include + #include ++#include + + #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 "); + 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 "); + 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 + #include +@@ -74,6 +64,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include +-#include ++#include ++#include + #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 + #include + #include +-#include ++#include + + #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 : ""); ++ __func__, new_parent ? new_parent->bus_id : ""); + 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 + #include + #include ++#include + #include + #include + +@@ -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 + #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 + #include + #include +-#include + #include + + 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 + #include ++#include + + #include + +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 "); ++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 + #include + #include +-#include + #include + + #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 + * +@@ -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 +@@ -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 + #include + #include ++#include + + 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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include +-#include + #include + + #include +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 + #include + #include ++#include + #include +-#include + + #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 + #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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* ++ * 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 + * +- * 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 , 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 +@@ -54,9 +18,6 @@ + #include + #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 + #include + #include ++#include + #include +-#include ++#include + #include + #include + #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 + #include ++#include + #include + + 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 + #include + #include ++#include + #include + #include + +@@ -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@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 + #include + #include + #include +@@ -28,7 +29,6 @@ + #include + #include + #include +-#include + + #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 + #include + #include +-#include + + #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 ++ * Copyright 2008 IBM, Inc. ++ * by Konrad Rzeszutek ++ * Copyright 2008 ++ * by Konrad Rzeszutek ++ * ++ * 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 ++ * Updated comments and copyrights. (v0.4.9) ++ * ++ * 11 Feb 2008 - Konrad Rzeszutek ++ * Converted to using ibft_addr. (v0.4.8) ++ * ++ * 8 Feb 2008 - Konrad Rzeszutek ++ * Combined two functions in one: reserve_ibft_region. (v0.4.7) ++ * ++ * 30 Jan 2008 - Konrad Rzeszutek ++ * Added logic to handle IPv6 addresses. (v0.4.6) ++ * ++ * 25 Jan 2008 - Konrad Rzeszutek ++ * Added logic to handle badly not-to-spec iBFT. (v0.4.5) ++ * ++ * 4 Jan 2008 - Konrad Rzeszutek ++ * Added __init to function declarations. (v0.4.4) ++ * ++ * 21 Dec 2007 - Konrad Rzeszutek ++ * Updated kobject registration, combined unregister functions in one ++ * and code and style cleanup. (v0.4.3) ++ * ++ * 5 Dec 2007 - Konrad Rzeszutek ++ * Added end-markers to enums and re-organized kobject registration. (v0.4.2) ++ * ++ * 4 Dec 2007 - Konrad Rzeszutek ++ * Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1) ++ * ++ * 28 Nov 2007 - Konrad Rzeszutek ++ * 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 ++ * Added text attributes emulating OpenFirmware /proc/device-tree naming. ++ * Removed binary /sysfs interface (v0.3) ++ * ++ * 29 Aug 2007 - Konrad Rzeszutek ++ * Added functionality in setup.c to reserve iBFT region. (v0.2) ++ * ++ * 27 Aug 2007 - Konrad Rzeszutek ++ * First version exposing iBFT data via a binary /sysfs. (v0.1) ++ * ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IBFT_ISCSI_VERSION "0.4.9" ++#define IBFT_ISCSI_DATE "2008-Mar-14" ++ ++MODULE_AUTHOR("Peter Jones and \ ++Konrad Rzeszutek "); ++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 ++ * Copyright 2007 IBM, Inc. ++ * by Konrad Rzeszutek ++ * Copyright 2008 ++ * by Konrad Rzeszutek ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* ++ * 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 ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#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 \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 + #include + #include ++#include + #include + #include + +@@ -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 + #include + #include +-#include + #include + #include + #include + #include +-#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 "); ++MODULE_AUTHOR("Ian Campbell , " ++ "Wolfram Sang "); + 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 ++ * 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 +@@ -34,14 +20,16 @@ + #include + + #include ++#include + #include + + #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 "); +-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 "); + 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 or + * ++ * Copyright (c) 2008 PIKA Technologies ++ * Sean MacLennan ++ * + * Based on original work by + * Ian DaSilva + * Armin Kuster +@@ -39,12 +42,17 @@ + #include + #include + #include ++ ++#ifdef CONFIG_IBM_OCP + #include + #include ++#else ++#include ++#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 "); + 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 "); + 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 + #include + #include +-#include + #include + #include + #include +- + #include + #include + #include +@@ -34,13 +33,9 @@ + #include + #include + +-#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 "); ++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 "); + 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 + #include + #include ++#include + + 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, "); + 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 ++ * ++ * licensed under the terms outlined in the file COPYING. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* 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 "); +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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + + #include + ++#include ++ ++ + /*-------------------------------------------------------------------------*/ + + #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 + #include + #include ++#include + #include +-#include + + #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 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 + . + + 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 + #include + ++#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 + #include + #include +@@ -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 + #include + #include + #include + ++#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 +@@ -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 + #include + ++#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 +@@ -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 ++#include ++#include ++#include ++ ++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@cecmow.enet.dec.com (Igor Abramov) +- * mlord@pobox.com (Mark Lord) ++ * mlord@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 + #include +@@ -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 + #include + ++#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 + #include + +- +-/** +- * 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 " +- ".\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 + #include + #include ++#include + #include +-#include + + #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 + #include + #include ++#include + + #include +-#include + + #include + #include +@@ -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 + #include + #include +-#include + + #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 +- + #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 +- + #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 "); + 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 +- + #include + + #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 +- + #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 +- + #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 +- + #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 "); ++MODULE_AUTHOR("QLogic "); + 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 + #include + #include ++#include ++#include ++#include + #include + + #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 + #include + #include ++#include + + #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 + #include + #include +- ++#include + + #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 ++#include ++#include ++#include ++#include ++ ++#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<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@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 ++#include + + #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<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 + #include + #include ++#include ++#include + #include + #include + +@@ -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<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 ++ + #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 \ +- <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 ++#include ++ ++#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 ++#include ++ ++#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 ++ ++#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 + + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ ++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 + #include + #include +- +-#include ++#include + + #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 + + 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 + #include + #include +-#include + #include + #include + #include +@@ -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 ++#include ++#include ++ ++#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 + + #include ++#include ++#include + + #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 + * 2004 Oliver Schwartz , +@@ -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 +@@ -77,7 +79,6 @@ + #include + #include + +-#define DRIVER_VERSION "v0.0.6" + #define DRIVER_AUTHOR "Marko Friedemann " + #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 - 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); + 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 + #include + #include ++#include + #include + + #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 "); + 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 "); + 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 "); + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + #include + #include ++#include + + #define KB_ROWS 7 + #define KB_COLS 11 +@@ -494,3 +495,4 @@ module_exit(spitzkbd_exit); + MODULE_AUTHOR("Richard Purdie "); + 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 "); + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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<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 "); ++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 + #include + #include +-#include ++#include + + #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 + #include + +-#ifdef CONFIG_ARM +-#include +-#ifdef CONFIG_ARCH_OMAP +-#include +-#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 + #include + #include ++#include + + + #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 "); + 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@wolfsonmicro.com or linux@wolfsonmicro.com ++ * Parts Copyright : Ian Molton ++ * Andrew Zabolotny ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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@wolfsonmicro.com or linux@wolfsonmicro.com ++ * Parts Copyright : Ian Molton ++ * Andrew Zabolotny ++ * Russell King ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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@wolfsonmicro.com or linux@wolfsonmicro.com ++ * Parts Copyright : Ian Molton ++ * Andrew Zabolotny ++ * Russell King ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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@wolfsonmicro.com or linux@wolfsonmicro.com ++ * Parts Copyright : Ian Molton ++ * Andrew Zabolotny ++ * Russell King ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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@wolfsonmicro.com or linux@wolfsonmicro.com ++ * Parts Copyright : Ian Molton ++ * Andrew Zabolotny ++ * Russell King ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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 ++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #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 + +-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 + #include + +-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 + #include + +-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 + +-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 + #include + +-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 + +-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 "); ++MODULE_AUTHOR("Márton Németh "); + 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 + #include +@@ -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 + #include + +-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 ++ * ++ * Author: Rod Whitby ++ * ++ * Based on leds-spitz.c ++ * Copyright 2005-2006 Openedhand Ltd. ++ * Author: Richard Purdie ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++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 "); ++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 + #include + +-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 + #include + +-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 +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-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 "); +-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 ++ * ++ * 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 ++#include ++#include ++#include ++#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 "); ++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 + #include + #include +-#include + + #include + +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 + #include + #include ++#include + + #include +-#include + #ifdef CONFIG_PPC + #include + #include +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 "); + 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 "); + 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 "); + 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 + #include + #include +-#include ++#include + #include + #include + #include +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 + #include + #include + #include ++#include ++#include + + #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 + #include + #include + #include + #include ++#include + + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + #include + #include ++#include ++#include + +-#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 "); ++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 + #include +@@ -22,6 +19,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #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 + */ +-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 + #include + #include ++#include + + #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 + #include + +-#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 +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 ++ 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 */ ++ Pavel Mihaylov ++ 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@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 +@@ -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 ++ */ ++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 ++ + #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; imulti_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 ++ + #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;iprops.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 ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++ This program is free software; you can redistribute it and/or 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 ++ ++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 ++ * ++ * This program is free software; you can redistribute it and/or 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 +- +- Support for KWorld DVB-S 100 by Vadim Catana +- +- This program is free software; you can redistribute it and/or 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 ++ * ++ * Support for KWorld DVB-S 100 by Vadim Catana ++ * ++ * Support for CX24123/CX24113-NIM by Patrick Boettcher ++ * ++ * This program is free software; you can redistribute it and/or ++ * 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 + #include +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ ++/* 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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++ ++#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 "); ++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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ * ++ * This program is free software; you can redistribute it and/or 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; ii2c, &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 ++ Copyright (C) 2008 Matthias Schwarzott + + This 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 "); + 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 ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++ This program is free software; you can redistribute it and/or 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 ++ ++#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 +- +-This program is free software; you can redistribute it and/or 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 ++ * Copyright (C) 2005-8 Patrick Boettcher ++ * ++ * This program is free software; you can redistribute it and/or 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 + #include +@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + #include + #include + +-#include "dvb_frontend.h" +-#include "s5h1420.h" ++#include + + ++#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 +- +- This program is free software; you can redistribute it and/or 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 ++ * Copyright (C) 2005-8 Patrick Boettcher ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ * Copyright (C) 2005 Patrick Boettcher ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ ++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 + #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 ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++ ++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<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 + #include + ++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 "); + 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 + #include + #include ++#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 /* copy to/from user */ + #include /* kernel radio structs */ + #include +-#include /* Lock for the I/O */ + + #include /* 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 /* 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 + * Version 1.0.7 + * - usb autosuspend support ++ * - unplugging fixed + * + * ToDo: + * - add seeking support +@@ -97,10 +98,10 @@ + /* driver definitions */ + #define DRIVER_AUTHOR "Tobias Lorenz " + #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 /* Initdata */ + #include /* request_region */ + #include /* radio card status report */ ++#include + #include /* outb, outb_p */ + #include /* copy to/from user */ + #include /* 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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++ ++#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 "); ++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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++ ++#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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++ ++#include "au0828.h" ++ ++#include ++ ++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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++ ++/* 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@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 ++ * 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 + #include + #include ++#include + + /* ---------------------------------------------------------- */ + /* 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 + #include +-#include + #include + #include + +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 + #include + #include ++#include + + #include + +@@ -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 + #include + +-//#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 ++ * (c) 2004 Gerd Knorr ++ * (c) 2008 Steven Toth ++ * - 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + #include +@@ -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= 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= 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= insmod option:\n", +- core->name); ++ err_printk(core, "Here is a list of valid choices for the card= " ++ "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 "); + MODULE_AUTHOR("Gerd Knorr [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 + +-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 "); + MODULE_AUTHOR("Gerd Knorr [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 + #include +@@ -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 + + #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 ++ ++ (c) 2008 Devin Heitmueller ++ - Fixes for the driver to properly work with HVR-950 ++ ++ (c) 2008 Aidan Thornton ++ ++ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: ++ (c) 2004, 2005 Chris Pascoe ++ (c) 2004 Gerd Knorr [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 ++#include ++ ++#include "em28xx.h" ++#include ++#include ++ ++#include "lgdt330x.h" ++#include "zl10353.h" ++ ++MODULE_DESCRIPTION("driver for em28xx based DVB cards"); ++MODULE_AUTHOR("Mauro Carvalho Chehab "); ++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 + Markus Rechberger +@@ -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<devno); ++ em28xx_devused &= ~(1<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<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<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<bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { + em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); +- em28xx_devused&=~(1<= EM28XX_MAXBOARDS) { +- printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); +- em28xx_devused&=~(1<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<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]= 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 ++#include ++ + #include + #include + #include +- +-#define UNSET -1 ++#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) ++#include ++#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 + +-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 + +-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 + #include + #include +-#include + + #include + #include +@@ -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 + + MODULE_AUTHOR("Stelian Pop "); +-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 ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#ifdef CONFIG_MT9M001_PCA9536_SWITCH ++#include ++#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 "); ++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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#ifdef CONFIG_MT9M001_PCA9536_SWITCH ++#include ++#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 "); ++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 + #include + #include +-#include + #include + #include + #include +@@ -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 ++#include + #include + #include + #include +-#include ++ ++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 + #include +- ++#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 + #include ++#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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#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 + #include + #include +-#include + #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 ", + (hdw->flag_ok ? " " : " "), + (hdw->flag_init_ok ? " " : " "), + (hdw->flag_disconnected ? " " : + " "), + (hdw->flag_tripped ? " " : ""), +- (hdw->flag_decoder_missed ? " " : "")); ++ (hdw->flag_decoder_missed ? " " : ""), ++ 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 ? + " " : + (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 ? + "" : " "), + (hdw->state_encoder_run ? +- " " : " "), ++ (hdw->state_encoder_runok ? ++ " " : ++ " ") : ++ (hdw->state_encoder_runok ? ++ " " : ++ " ")), + (hdw->state_encoder_config ? + " " : + (hdw->state_encoder_waitok ? +- "" : " ")), ++ "" : " ")), + (hdw->state_usbstream_run ? +- " " : " ")); +- break; ++ " " : " "), ++ (hdw->state_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 + #include +-#include + #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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#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 "); ++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 + #include + +-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 + +-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 + #include ++#include ++#include + + #include "saa7134-reg.h" + #include "saa7134.h" ++#include "tuner-xc2028.h" + #include + #include ++#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 */ +- .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 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] = { + /* , Sergey */ ++ /* Beholder Intl. Ltd. 2008 */ ++ /*Dmitry Belimov */ + .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 */ + .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 */ + .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 */ + .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 */ + .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 */ + .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 */ ++ /* Beholder Intl. Ltd. 2008 */ ++ /*Dmitry Belimov */ + .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 */ + .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 */ + .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 */ + .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 */ + .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 */ + .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 */ + .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@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 */ ++ .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 */ ++ .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 */ ++ .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@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 + #include "dvb-pll.h" ++#include + + #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 [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 ++ * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004) ++ * ++ * Changes by T.Adachi (tadachi@tadachi-net.com) ++ * - support audio, video scaler etc, and checked the initialize sequence. ++ * ++ * Cleaned up by Hans Verkuil ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++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 + #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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++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 */ ++ 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 "); ++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@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 + #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@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@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@infradead.org) ++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) + * + * Copyright (c) 2007 Michel Ludwig (michel.ludwig@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@infradead.org) ++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@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; /* */ ++ /* Make sure that lineBuffer can store two lines of data */ ++ len = 3 * data_w; /* */ + 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 + #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 + #include + +-#include ++#include + #include + #include + #include +@@ -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 "); + 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 _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 + #include + #include ++ + #include + +-#include ++#include + #include + + /* ------------------------------------------------------------------ */ +@@ -30,7 +31,7 @@ + MODULE_AUTHOR("Gerd Knorr [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 _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 ++#include + #include + #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, +- "lave or attached aster name type flags magic "); +- i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n"); ++ seq_printf(m, "lave or attached 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 + #include +@@ -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 + #include + +-//#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 + +-#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 + #include ++#include + + #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 ++ * Copyright (c) 2007 Philipp Zabel ++ * ++ * This file may be distributed under the terms of the GNU GPL license. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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<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 "); +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 ++ * ++ * This program is free software; 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 ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 "); ++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 + + #include +-#include + #include + #include + +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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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, "[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 ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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, "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 + + #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 + + #include ++#include + #include + #include + #include +@@ -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 + #include + ++#include ++ + #include + + #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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ * ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 , " ++ "Eugene Konev "); ++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 + #include + #include ++#include + + 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=,,\""); ++MODULE_PARM_DESC(phram, "Memory region to map. \"phram=,,\""); + + + 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 "); + 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 "); +- ++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 "); + 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@cotw.com) + * ++ * ++ * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263 ++ * Richard Genoud (richard.genoud@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 + #include + ++#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 /* 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 + * +@@ -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 + + #include +- ++#include + + #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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 "); ++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 "); + 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 + #include + #include +-#include + #include ++#include + + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 "); + 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 + #include + +-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 + #include ++#include + #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 ++ ++/* 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 + #include + #include +- +-#include + #include + ++#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 + - Increase *read_eeprom udelay to workaround oops with 2 cards. + v1.19b 08Nov2002 Marc Zyngier +- - Introduce driver model for EISA cards. ++ - Introduce driver model for EISA cards. ++ v1.20 04Feb2008 Ondrej Zary ++ - 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 +-#ifdef CONFIG_MCA + #include +-#endif +-#include ++#include ++#include + #include + #include + #include +@@ -97,10 +96,6 @@ static int max_interrupt_work = 10; + + static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@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@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 + #include + #include ++#include + +-#include + #include + #include + #include +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 +- for more information about +- optional driver parameters. +- Questions concerning this driver may be addressed to: +- +- +- 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 . 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 +- * Copyright(c) 2006 Jay Cliburn +- * +- * 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 +-#include +- +-#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... +- * +- * +- * 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. +- * +- */ +- +-/* +- * 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 +- * Copyright(c) 2006 Jay Cliburn +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Copyright(c) 2006 Jay Cliburn +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Copyright(c) 2006 Jay Cliburn +- * +- * 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 +-#include +- +-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 +- * Copyright(c) 2006 Jay Cliburn +- * +- * 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 +- * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei, +- * Xinzhu 302, TAIWAN, REPUBLIC OF CHINA +- * +- * Chris Snook +- * Jay Cliburn +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#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 , Chris Snook , Jay Cliburn "); +-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: +- * +- * 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. +- * +- */ +-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 +- * Copyright(c) 2006 Jay Cliburn +- * +- * 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 +-#include +-#include +-#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 ++ * Copyright(c) 2006 Jay Cliburn ++ * ++ * 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 ++ * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei, ++ * Xinzhu 302, TAIWAN, REPUBLIC OF CHINA ++ * ++ * Chris Snook ++ * Jay Cliburn ++ * ++ * 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 ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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: ++ * ++ * 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. ++ * ++ */ ++ ++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 ++ * Copyright(c) 2006 Jay Cliburn ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * Copyright(c) 2006 Jay Cliburn ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * Copyright(c) 2006 Jay Cliburn ++ * 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 ++#include ++ ++#define ATLX_DRIVER_VERSION "2.1.1" ++MODULE_AUTHOR("Xiong Huang , \ ++ Chris Snook , Jay Cliburn "); ++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, "); + 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 "); + 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 + #include + #include "t3cdev.h" +-#include + #include + + 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 + #include +-#include + #include + #include + #include +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 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 + #include + +-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 + #include + #include ++#include + + #include + +@@ -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;itx_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 "); + 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 + #include + #include +-#include ++#include + #include + + #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 + #include + #include ++#include ++#include + + #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 + #include + #include +-#include + #include + #include + #include +@@ -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 "); + 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 + #include + #include ++#include + + #ifdef CONFIG_MACH_MAINSTONE + #include +@@ -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 + +-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 + #include + +-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 ++#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, "); + 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@idt.com) ++ * Copyright 2006 Felix Fietkau ++ * Copyright 2008 Florian Fainelli ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 "); ++MODULE_AUTHOR("Felix Fietkau "); ++MODULE_AUTHOR("Florian Fainelli "); ++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 "); ++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 "); + 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 + + #include ++#include + + #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 +- + #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 + + #include ++#include + #include + + #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 + * + * Based on the 64360 driver from: +- * Copyright (C) 2002 rabeeh@galileo.co.il ++ * Copyright (C) 2002 Rabeeh Khoury ++ * Rabeeh Khoury + * + * Copyright (C) 2003 PMC-Sierra, Inc., + * written by Manish Lachwani +@@ -16,6 +17,9 @@ + * Copyright (C) 2004 Steven J. Hill + * + * ++ * Copyright (C) 2007-2008 Marvell Semiconductor ++ * Lennert Buytenhek ++ * + * This program is free software; you can redistribute 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 + #include + +-#include + #include + #include + #include +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 "); + 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 + #include + ++/* 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 ++#include ++#include ++#include ++ ++#include ++#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 ++ * 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_segssize); + } + /* 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 +@@ -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; idev; ++ 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 "); + 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#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 +- +-/******************************************************************************* +-** +-** 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@syskonnect.de) +- * Mirko Lindner (mlindner@syskonnect.de) +- * +- * Address all question to: linux@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 +-#include +-#include +- +-/****************************************************************************** +- * +- * 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@syskonnect.de) +- * Mirko Lindner (mlindner@syskonnect.de) +- * +- * Address all question to: linux@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: +- * +- * +- * +- * "h/skdrv1st.h" +- * +- * +- * +- * +- * +- * +- * +- * +- * +- * +- * +- * +- * +- * +- * those three depending on kernel version used: +- * +- * +- * +- * +- * +- * "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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 "); +-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; iTxPort[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; iTxPort[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; iGIni.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; iGIni.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; iVNextRxd = 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; iGIni.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; iGIni.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; iTxDescrPerRing; 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; imc_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; iGIni.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; iGIni.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; iGIni.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; iGIni.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.LenPnmiStruct)? +- Ioctl.Len : sizeof(pAC->PnmiStruct))) { +- return -EFAULT; +- } +- Size = SkGeIocMib(pNet, Ioctl.Len, cmd); +- if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct, +- Ioctl.Lenifr_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 100 +- ** 100HD Half Off None 100 +- ** 10FD Full Off None 10 +- ** 10HD Half Off None 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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->IndexIndex] != 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 , 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 , 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 (1name); + 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 + + /* + * 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<> 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<> 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 + #include + #include +-#include +-#include ++#include ++#include + #include + #include + #include +@@ -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<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 + #include +@@ -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 \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@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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include /* Processor type for cache alignment. */ +-#include +- +- +-/* 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@scyld.com\n" +-KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n"; +- +-MODULE_AUTHOR("Donald Becker "); +-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 . */ +-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 + #include + #include ++#include + #include ++#include + + #include + #include +@@ -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 + #include + #include +-#include + #include + + #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 + #include + #include ++#include + #include + + #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: + + . ++ ++ 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 . +- 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: + + . +- +- 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 . +- 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 + + #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 + #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 ++ ++#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 + * Copyright (c) 2006-2007 Nick Kossifidis + * Copyright (c) 2007 Matthew W. S. Bell +@@ -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 +- * +- * 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 +-#include +- +-#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 +- * +- * 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 +- +-/* 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 + #include + #include ++#include + #include + #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 + #include + #include ++#include + + + /* 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 ++ ++ This program is free software; you can redistribute it and/or 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 ++ ++ ++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 ++#include ++#include ++#include ++ ++ ++/*** 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +-#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 +- +- This program is free software; you can redistribute it and/or 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 +-#include +-#include +-#include +-#include +-#include +- +-#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 +-#include +- +-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 +- +- 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 +-#include +-#include +-#include +- +- +-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 +-#include +-#include +-#include +-#include +-#include +- +- +-/* 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 +- +- 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 +-#include +-#include +-#include +- +- +-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 +- +-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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- This program is free software; you can redistribute it and/or 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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- This program is free software; you can redistribute it and/or 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 +- +- +-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 +-#include +- +- +-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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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; keyidxflags & (1<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; keyidxflags & (1<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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +-#include +-#include +- +-#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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +- +-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 +- +- This program is free software; you can redistribute it and/or 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 +- +- +-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 +-#include +-#include +- +- +-#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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +- +-#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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +- +-/* 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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +- +-#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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +- +- This program is free software; you can redistribute it and/or 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 +- +- +-#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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 +-#include +-#include +-#include +-#include +-#include +- +-#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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- 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 , +- Stefano Brivio +- Michael Buesch +- Danny van Dyk +- Andreas Jaggi +- +- This program is free software; you can redistribute it and/or 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 +- +- +-/* 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 . 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 . 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 ++ * 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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ * ++ *****************************************************************************/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * 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 ++ ++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 + +-#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 + #include + ++#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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * +- *****************************************************************************/ +- +-#ifndef __iwl4965_io_h__ +-#define __iwl4965_io_h__ +- +-#include +- +-#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 + +-#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 + #include + ++#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("<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 + #include + +-/* 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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ *****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++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 ++ * 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 ++ * 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 ++ * 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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ *****************************************************************************/ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++ ++#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 ++ * 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 ++#include ++#include ++#include ++ ++#include ++ ++#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 ++ * 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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ *****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ * ++ *****************************************************************************/ ++ ++#ifndef __iwl_io_h__ ++#define __iwl_io_h__ ++ ++#include ++ ++#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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ * ++ *****************************************************************************/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * 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 ++ ++#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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ *****************************************************************************/ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 ++ * 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 ++#include ++ ++ ++#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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ * ++ *****************************************************************************/ ++ ++#include ++ ++#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 ++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 ++ * ++ *****************************************************************************/ ++#ifndef __iwl_sta_h__ ++#define __iwl_sta_h__ ++ ++#include ++ ++#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 + ++#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 + ++#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 */ +- 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 +-#include + #include + + #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 ++#include + #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 + #include + #include ++#include + + #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 +-#include +-#include +-#include +- +-#include +- +-#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 + #include + #include ++#include + + #include + #include +@@ -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, "", sizeof("")); ++ 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 +-#include +-#include +-#include + #include +- +-#include +-#include +- + #include + + #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 +-#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 +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 ++ * Copyright (c) 2007, Christian Lamparter ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 ++#include ++#include ++ ++#include ++ ++#include "p54.h" ++#include "p54common.h" ++ ++MODULE_AUTHOR("Michael Wu "); ++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 ++ * Copyright (c) 2007, Christian Lamparter ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "p54.h" ++#include "p54pci.h" ++ ++MODULE_AUTHOR("Michael Wu "); ++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 ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "p54.h" ++#include "p54usb.h" ++ ++MODULE_AUTHOR("Michael Wu "); ++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 ++ * ++ * Based on the islsm (softmac prism54) driver, which is: ++ * Copyright 2004-2006 Jean-Baptiste Note , 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 +- * Copyright (c) 2007, Christian Lamparter +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 +-#include +-#include +- +-#include +- +-#include "p54.h" +-#include "p54common.h" +- +-MODULE_AUTHOR("Michael Wu "); +-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 +- * Copyright (c) 2007, Christian Lamparter +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "p54.h" +-#include "p54pci.h" +- +-MODULE_AUTHOR("Michael Wu "); +-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 +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "p54.h" +-#include "p54usb.h" +- +-MODULE_AUTHOR("Michael Wu "); +-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 +- * +- * Based on the islsm (softmac prism54) driver, which is: +- * Copyright 2004-2006 Jean-Baptiste Note , 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 + #include + #include ++#include + #include + #include + #include +@@ -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; idwell_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 . + +- 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 + + + 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 + + + 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 + + + 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 + + + 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 + + + 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 + + + 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 + + + This program is free software; you can redistribute it and/or modify +@@ -27,23 +27,24 @@ + #define RT2X00_H + + #include +-#include + #include + #include + #include ++#include + #include + #include + + #include + + #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 + + + 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 + + + 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 + + + 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 + + + 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 + + + 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 + + + This program is free software; you can redistribute it and/or modify +@@ -23,7 +23,6 @@ + Abstract: rt2x00 firmware loading routines. + */ + +-#include + #include + #include + +@@ -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 ++ ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++ ++#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 ++ ++ ++ This program is free software; you can redistribute it and/or 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 + + + 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 + + + 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 + + + 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 + + + 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 ++ ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++ ++#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 ++ ++ ++ This program is free software; you can redistribute it and/or 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 ++ ++/** ++ * 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 + + + 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 + + + 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 +- +- +- This program is free software; you can redistribute it and/or 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 + + + 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 + + + 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 + + + This program is free software; you can redistribute it and/or modify +@@ -24,6 +24,7 @@ + Supported chipsets: RT2561, RT2561s, RT2661. + */ + ++#include + #include + #include + #include +@@ -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 + + + 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 + + + This program is free software; you can redistribute it and/or modify +@@ -24,6 +24,7 @@ + Supported chipsets: rt2571W & rt2671. + */ + ++#include + #include + #include + #include +@@ -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 + + + 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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * 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 ++ * ++ * Based on a previous patch from Jon Smirl ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++ ++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, 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 + #include + #include + #include +@@ -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 + #include ++#include + #include + #include + #include +@@ -31,6 +32,7 @@ + #include + #include + #include ++#include + #include "iova.h" + #include "intel-iommu.h" + #include /* 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 + #include + #include ++#include + #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 + #include + #include ++#include + #include /* 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@intel.com) ++ * Copyright (C) Shaohua Li (shaohua.li@intel.com) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++#include ++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 + #include + #include ++#include + #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 + #include ++#include + #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 + + #include ++#include + #include + + #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 + + #include ++#include + #include + + #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 ++#include + #include + + /** +@@ -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 + + #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 , Jamie Lenehan "); ++MODULE_AUTHOR("Paul Mundt , " ++ "Jamie Lenehan , " ++ "Angelo Castello "); + 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 + #include + +-#include + #include + #include + +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 + #include + #include ++#include + #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 + #include + #include ++#include + + #include + #include + #include +-#include + #include + + #include +@@ -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 + #include + #include ++#include + + #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 +- ++ For details please refer to the documentation provided by IBM at ++ + +- 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@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@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 +-#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@de.ibm.com) ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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@de.ibm.com) ++ * ++ */ ++ ++#ifndef _CTCM_DBUG_H_ ++#define _CTCM_DBUG_H_ ++ ++/* ++ * Debug Facility stuff ++ */ ++ ++#include ++ ++#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@millenux.com) ++ * Peter Tiedemann (ptiedem@de.ibm.com) ++ * MPC additions : ++ * Belinda Thompson (belindat@us.ibm.com) ++ * Andy Richter (richtera@us.ibm.com) ++ */ ++ ++#undef DEBUG ++#undef DEBUGDATA ++#undef DEBUGCCW ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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@millenux.com) ++ * Peter Tiedemann (ptiedem@de.ibm.com) ++ * MPC additions : ++ * Belinda Thompson (belindat@us.ibm.com) ++ * Andy Richter (richtera@us.ibm.com) ++ */ ++#ifndef _CTCM_FSMS_H_ ++#define _CTCM_FSMS_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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@millenux.com) ++ * Dieter Wellerdiek (wel@de.ibm.com) ++ * Martin Schwidefsky (schwidefsky@de.ibm.com) ++ * Denis Joseph Barrow (barrow_dj@yahoo.com) ++ * Jochen Roehrig (roehrig@de.ibm.com) ++ * Cornelia Huck ++ * MPC additions: ++ * Belinda Thompson (belindat@us.ibm.com) ++ * Andy Richter (richtera@us.ibm.com) ++ * Revived by: ++ * Peter Tiedemann (ptiedem@de.ibm.com) ++ */ ++ ++#undef DEBUG ++#undef DEBUGDATA ++#undef DEBUGCCW ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 "); ++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@millenux.com) ++ * Peter Tiedemann (ptiedem@de.ibm.com) ++ */ ++ ++#ifndef _CTCM_MAIN_H_ ++#define _CTCM_MAIN_H_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#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@us.ibm.com) ++ * Andy Richter (richtera@us.ibm.com) ++ * Peter Tiedemann (ptiedem@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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include /* instead of ok ? */ ++#include ++#include ++#include /* instead of ok ? */ ++#include /* instead of ok ? */ ++#include ++#include ++#include ++ ++#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@de.ibm.com) ++ * ++ * MPC additions: ++ * Belinda Thompson (belindat@us.ibm.com) ++ * Andy Richter (richtera@us.ibm.com) ++ */ ++ ++#ifndef _CTC_MPC_H_ ++#define _CTC_MPC_H_ ++ ++#include ++#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@de.ibm.com) ++ * ++ */ ++ ++#undef DEBUG ++#undef DEBUGDATA ++#undef DEBUGCCW ++ ++#include ++#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@de.ibm.com, felfert@millenux.com) +- * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) +- * Arnaldo Carvalho de Melo +- Peter Tiedemann (ptiedem@de.ibm.com) +- * Driver Model stuff by : Cornelia Huck +- * +- * 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@de.ibm.com) +- * Martin Schwidefsky (schwidefsky@de.ibm.com) +- * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) +- * Jochen Röhrig (roehrig@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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include +- +-#include "fsm.h" +-#include "cu3088.h" +- +-#include "ctcdbug.h" +-#include "ctcmain.h" +- +-MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@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 +- * not 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 +- * not 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@de.ibm.com, felfert@millenux.com) +- Peter Tiedemann (ptiedem@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 +-#include +- +-#include +-#include +- +-#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 +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +- +-#include +- +-#include +-#include +-#include +-#include +- +-#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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#ifndef __QETH_CORE_H__ ++#define __QETH_CORE_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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 "); ++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 , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#include ++#include ++#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 , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#ifndef __QETH_CORE_MPC_H__ ++#define __QETH_CORE_MPC_H__ ++ ++#include ++ ++#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 , ++ * Frank Blaschka ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 , ++ * Frank Blaschka ++ */ ++ ++#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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#include ++#include ++#include ++ ++#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 +- * +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#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 +- * +- */ +-#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 +- * +- */ +-#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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 "); ++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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#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 "); ++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 , ++ * Frank Pavlic , ++ * Thomas Spatzier , ++ * Frank Blaschka ++ */ ++ ++#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 "/\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 /\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@de.ibm.com) +- * Rewritten by +- * Frank Pavlic (fpavlic@de.ibm.com) and +- * Thomas Spatzier +- * +- * This program is free software; you can redistribute 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 "); +-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 +- * Thomas Spatzier +- * +- */ +-#include +-#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 +- * Thomas Spatzier +- * Frank Pavlic +- * +- */ +-#ifndef __QETH_MPC_H__ +-#define __QETH_MPC_H__ +- +-#include +- +-#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 +- * +- */ +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Frank Pavlic +- * +- */ +-#include +-#include +- +-#include +- +-#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 "/\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 /\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 +- * +- */ +-#ifndef __QETH_TSO_H__ +-#define __QETH_TSO_H__ +- +-#include +-#include +-#include +-#include +-#include +-#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@de.ibm.com!\n", __FUNCTION__); ++ "linux390@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 + #include + #include ++#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 + #include + #include ++#include + + /* Sigh, math-emu. Don't ask. */ + #include + #include + #include + +-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 + , and the files + and + 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 + #include + #include +-#include + #include + #include /* 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 + #include /* ssleep prototype */ + #include +-#include ++#include + #include + + #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 + #include + #include +-#include + + #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 + #include + #include ++#include + #include + #include + #include + #include +-#include + + #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 + #include + #include +-#include ++#include + + #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 + #include + #include +-#include + + #include + #include +@@ -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 + #include + #include +-#include + + #include + +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 + #include + #include +-#include + + #include + +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 + #include + #include ++#include + + #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 + +-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 + #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 + +-#include /* Needed for MUTEX init macros */ + #include + #include + #include +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 ++#include ++#include + + #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 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 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 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 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 + * mbxStatus +@@ -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 + #include + #include +-#include + #include + #include + #include +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 +-#include ++#include + + #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 + #include + #include ++#include + + #include + #include +@@ -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 + +-#include + #include + #include + #include +@@ -367,10 +366,6 @@ + #include + #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 + #include + #include +-#include ++#include ++#include + + #include + #include +@@ -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 + #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 + +-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 + #include + +-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, " "); + 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 + #include + #include +- + #include +-#include "scsi.h" ++ ++#include ++#include ++#include + #include + #include ++#include + + #include + + #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 +- +-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 Devfs support + */ + +-static const char *verstr = "20080221"; ++static const char *verstr = "20080224"; + + #include + +@@ -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 + #include + #include ++#include + + #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 + #include + ++#include ++ + #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 + #include + #include ++#ifdef CONFIG_PPC_CPM_NEW_BINDING ++#include ++#endif + + #include + #include +@@ -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 ++ * ++ * 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 ++#include ++#include ++#include ++ ++#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, "[,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 + #include + #include +-#include + #include + #include + #include +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 , + * 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 + #include +- + #include + + #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 ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++ ++/* ++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 + #include ++#include ++#include ++#include + + #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 + #include + #include ++#include + #include + #include + +@@ -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 +- * Copyright 2007 Michael Buesch ++ * Copyright 2007-2008 Michael Buesch + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -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 ++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 ++ * Copyright (C) 2005 Martin Langer ++ * Copyright (C) 2005 Stefano Brivio ++ * Copyright (C) 2005 Danny van Dyk ++ * Copyright (C) 2005 Andreas Jaggi ++ * ++ * 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 + +-#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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#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 "); +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 + #include + #include ++#include + + #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 + #include + #include + #include +@@ -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 + #include + +-#include + #include + #include + +@@ -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 + #include + #include ++#include + #include + + #include +@@ -27,6 +28,7 @@ + + + static struct usba_udc the_udc; ++static struct usba_ep *usba_ep; + + #ifdef CONFIG_USB_GADGET_DEBUG_FS + #include +@@ -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 ++ ++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@plexity.net) +- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka, +- * , 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 + #include + #include +-#include ++#include ++#include + + #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<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 +@@ -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 + #include + #include +-#include + + #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 + #include + #include ++#include + + /*-------------------------------------------------------------------*/ + /* 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@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 +@@ -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 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 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 + #include + #include +-#include + #include + #include + +@@ -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 - <<<<<<<<<<<<<<>>>>>>>>>", __FUNCTION__); ++ dbg("%s - RUNNING IN DOWNLOAD MODE", __func__); + + status = TiValidateI2cImage (serial); + if (status) { +- dbg ("%s - <<<<<<<<<<<<<<>>>>>>>>>", +- __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 - <<<<<<<<<<<<<<>>>>>>>>>>>>>>", +- __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 - <<<<<<<<<<<<<<>>>>>>>>>>>", __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; iwrite_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 +@@ -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 " + #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 ++ Copyright (C) 2006, 2007, 2008 Kevin Lloyd + + 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 + */ + +-#define DRIVER_VERSION "v.1.2.8" +-#define DRIVER_AUTHOR "Kevin Lloyd " ++#define DRIVER_VERSION "v.1.2.9c" ++#define DRIVER_AUTHOR "Kevin Lloyd " + #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" + + #include +@@ -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@worldplus.com.cn) ++ * Copyright (C) 2006 S1 Corp. ++ * ++ * Original driver for 2.6.10 pl2303 driver by ++ * Greg Kroah-Hartman (greg@kroah.com) ++ * Changes for 2.6.20 by Harald Klein ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* 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 + #include + #include +-#include + #include + #include + +@@ -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 . +@@ -69,8 +69,8 @@ config USB_STORAGE_DPCM + There is a web page at . + + 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@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 ++#include ++#include ++#include ++ ++#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@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 + #include + #include ++#include + + /* + */ +@@ -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 "); +@@ -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 + #include + #include ++#include + #include + #include + +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 ++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + +-#include + #include + #include + +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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 , XenSource Inc, 2007 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++ ++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<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// => - */ + 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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#ifdef __ia64__ ++#include /* for is_kern_addr() */ ++#endif ++ ++#ifdef HAVE_XEN_PLATFORM_COMPAT_H ++#include ++#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 + #include + #include +-#include + #include + #include + +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 + . + ++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 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 +- . +- +- 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@samba.org (sfrench@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@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 + #include + #include +-#include + + #include + +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 + #include + #include +-#include + #include + + #include + #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 ++#include ++#include ++#include ++#include ++ ++#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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + + 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 + #include ++#include + #include + #include + #include +@@ -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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 + + #include ++#include + #include + + /* +@@ -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 +-#include +-#include +- +-#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 + #include + #include +-#include + + #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 + #include + #include ++#include + + #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 + #include ++#include + #include + #include + #include +@@ -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; ifree_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 ++#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 + #include + #include +-#include ++#include + + 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 + #include + #include +-#include ++#include + #include + #include + #include +@@ -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 :)) */ + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + + #include +@@ -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 + #include + #include ++#include + + #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 + #include + #include ++#include ++#include + + #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 + #include + +-#include + #include + + #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 + #include + #include ++#include + #include + #include + #include +@@ -26,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + + #include + +@@ -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 + #include + #include +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 + #include + #include ++#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 + #include + #include ++#include + + #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 + #include + #include ++#include + + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -35,8 +36,10 @@ + #include + #include + #include ++#include + + #include ++#include + + /* + * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 + #include + #include ++#include + + #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; ispinlock); +-} +-#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 + #include + #include ++#include + + #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; imaybe_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 + #include + #include +-#include + #include + #include + #include + #include + +-#include +-#include +-#include +- +-#include +- + #define MLOG_MASK_PREFIX ML_DLM_GLUE + #include + +@@ -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 ++ * ++ * 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 + #include + #include +-#include +- +-#include + + #define MLOG_MASK_PREFIX ML_SUPER + #include +@@ -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 + #include ++#include + + #define MLOG_MASK_PREFIX ML_INODE + #include +@@ -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 + #include + +-#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 ++#include ++ ++/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++ ++#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<8-char-hex-nodenum> ++ * ++ * 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<2-char-hex-major><2-char-hex-minor> ++ * ++ * 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<32-char-cap-hex-uuid><8-char-hex-nodenum> ++ * ++ * 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<8-char-hex-nodenum> */ ++struct ocfs2_control_message_setn { ++ char tag[OCFS2_CONTROL_MESSAGE_OP_LEN]; ++ char space; ++ char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN]; ++ char newline; ++}; ++ ++/* SETV<2-char-hex-major><2-char-hex-minor> */ ++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<32-char-cap-hex-uuid><8-char-hex-nodenum> */ ++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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++ ++#include "dlm/dlmapi.h" ++#include ++ ++/* ++ * 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 + #include + #include +- +-#include ++#include + + #define MLOG_MASK_PREFIX ML_SUPER + #include +@@ -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 + #include + #include ++#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 + #include ++#include + #include + #include + #include +@@ -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 + + #include +-#include ++#include + + #include + #include +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 + #include + #include +-#include + + #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 + #include + #include ++#include + #include ++#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 + #include + #include ++#include + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 +- * 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 +- +-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 +- * >=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 +-#include + #include + #include + #include /* 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 +- * 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 + #include +-#include + #include + #include + +@@ -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 + #include + #include ++#include + + #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 + #include + +-#include + #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 + #include +-#include + #include ++#include + + #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 + #include + #include ++#include + + 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 +- * 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 + #include +-#include + #include + #include + +@@ -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 + #include + #include ++#include ++#include + #include + +-#include + #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. +- * 0 Blocksize is valid. +- * 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 +- * 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 + #include + #include +-#include + #include + #include + #include +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 + #include +-#include + #include + + #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 + 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 ++ + /* 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 + #include "ecma_167.h" + #include "osta_udf.h" + + #include + #include +-#include +-#include + #include ++#include + ++#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 + #include /* for memset */ + #include +-#include ++#include + + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include ++#include + #include +-#include + + /* + * 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 ++#include + #include + + +@@ -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<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 + + #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 +-#include +-#include +-#include +-#include +-#include +- +-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 +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 + #endif /* !CONFIG_NUMA */ ++# include + + #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 + +-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 /* 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 + +-#include ++#ifdef CONFIG_ARCH_MX3 ++# include ++#endif + + #include + +-#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 +- +-#ifndef MXC_MAX_EXP_IO_LINES +-#define MXC_MAX_EXP_IO_LINES 0 ++#ifdef CONFIG_MACH_MX31ADS ++# include + #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 + +-/*! +- * @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 + +-/*! +- * @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 + +-#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 +- +-#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 +-#include ++#include + + .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 ++ ++#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 ++ ++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 ++#include + +-#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 ++ ++/* 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 ++ ++/* 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 +- +-/* 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 +-#include +-#include ++#include ++#include + + 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 ++ ++#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 ++ ++#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 +- +-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 ++#include + + 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 /* 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 ++ * 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 ++ ++/* 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 +- +- .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 +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 +- +- .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 /* 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 +- * +- * 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 +- * +- * 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 +- * +- * 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 +-#include +- +-#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 +- * +- * 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 +- * +- * 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 +-#include +- +-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 +- * +- * 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 +- * +- * 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 +- +-#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 ++ ++ .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 +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 ++ ++ .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 /* 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 ++ * ++ * 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 ++ * ++ * 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 ++ * ++ * 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 ++ * ++ * 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 ++#include ++ ++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 ++ * ++ * 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 ++ * ++ * 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 ++ ++#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 ++ ++ This program is free software; you can redistribute it and/or 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 ++#include ++#include + + /* + * 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 ++#include ++ ++/* 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 ++#include ++ ++/* 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 ++ ++/* ++ * 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 ++#include ++ ++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 ++ ++/* ++ * 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 ++ ++/* ++ * 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 + + /* 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 ++#include ++#include + + #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 +- +-#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 ++#include + +-#include ++#include ++#include ++#include + +-#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 ++ * 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 ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++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 + #include + +-#include + #include + +-#include +-#include +- + 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 +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 + #include +- +-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 + + 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 /* 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 +- +-/* +- * 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 ++ ++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 +-#include +-#include +-#include +- +-#include +-#include +- +-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 +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 ++ ++#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 +- +-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 + #include + +-#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 +-#include +- +-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 ++ + /* 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 +- +-#include +-#include +-#include +-#include +- +-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 +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 ++ ++#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 ++ + #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 + #include + #include +-#include + + #include + #include +@@ -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 + + /****************************************************************************/ +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 + #include + #include + +-#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 ++#include ++#include ++ ++#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 ++#include + + #include "defBF52x_base.h" + ++/* Include core specific register pointer definitions */ ++#include ++ + /* ==== 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 + #include + #include + +-#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 ++#include ++#include ++ ++#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 + #include + #include + +-#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 ++#include ++#include ++ ++#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 + #include + #include + +-#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 ++#include ++#include ++ ++#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 (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 + #include + #include + +-#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 ++#include ++#include ++ ++#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 + #include +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 +- +-/* +- * 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 +-#include +-#include +-#include +-#include +- +-/* +- * 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 +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 +-#include +- +-#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 +-#include +-#include +- +-#include +-#include +- +-/* +- * 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 +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@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 +-#include +-#include +-#include +- +-/* +- * 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 +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 + +-#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 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 +- +-/* +- * 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 +-#include +-#include +-#include +- +-#include +-#include +- +-/* +- * 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 +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 + #include + #include ++#include + + #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 . ++ * ++ * Copyright (C) 2007 FUJITSU LIMITED ++ * Copyright (C) 2007 Hidetoshi Seto ++ * ++ * This program is free software; you can redistribute it and/or ++ * 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 ++#else ++ ++#include ++#include ++#include ++ ++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 + +-#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 + + #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 + + #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 + ++#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 + * Copyright (C) 1999 Srinivasa Prasad Thirumalachar ++ * 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 +- */ +- +-#include +-#include +- +-#include +- +-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 +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 + #include + #include + #include +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 +-#include +-#include +-#include +-#include +- +- +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +-/* +- * 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 + + #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 + + #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 +- +-#ifdef __KERNEL__ +- +-/* +- * SMP- and interrupt-safe semaphores.. +- * +- * Copyright (C) 1996 Linus Torvalds +- * Copyright (C) 2004, 2006 Hirokazu Takata +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-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 +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 +- +-/* +- * 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 +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-/* +- * 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 +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 +-#include +-#include +-#include +- +-#include +-#include +- +-/* +- * 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 +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@samba.org) +- */ +- +-#ifdef __KERNEL__ +- +-#include +-#include +-#include +-#include +- +-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 +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@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 +-#include +-#include +-#include +- +-#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 +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 +-#include +-#include +- +-#include +- +-/* +- * 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 +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 ++ + #include + #include + #include +-#include + #include + + 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 ++#endif /* __powerpc64__ */ + + #include +- +-#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 + + /* 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 + #include + ++/* 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 ++#include ++#ifdef CONFIG_HIGHMEM ++#include ++#include ++#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 , ++ * Scott Wood ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++#include ++ ++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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++ ++#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 + #include + #include +- +-/* undef for production */ +-#define HIGHMEM_DEBUG 1 ++#include + + 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 + #include + +-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 ++#include + + #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 + +@@ -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 + ++#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 + +-#include +-#include ++#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 ++#include + + 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 ++ + 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 + #include ++#include + + /* + * 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 +- + #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 ++ * ++ * 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@samba.org) +- */ +- +-#ifdef __KERNEL__ +- +-#include +-#include +-#include +-#include +- +-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 +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 + #ifdef CONFIG_PPC64 + #include + #include +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 ++#include + + #include + +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 + +-#endif /* CONFIG_NUMA */ +- + #ifdef CONFIG_SMP + #include + #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 + #endif + +-#if defined(CONFIG_PQ2ADS) || defined (CONFIG_PQ2FADS) +-#include +-#endif +- + #ifdef CONFIG_PCI_8260 + #include + #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 + #endif + +-#if defined(CONFIG_MPC885ADS) +-#include +-#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 + #include +-#include + + #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 +-#include +-#include +-#include +- +-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 +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 ++ * Christian Borntraeger ++ */ ++ ++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 ++ ++#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 + + #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 + + #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 ++ ++/* 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 ++ ++/* 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 ++ ++#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 +- +-#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 +-#include +-#include +- +-#include +-#include +- +-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 +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@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 +- +-/* +- * 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; /* */ +- 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@caip.rutgers.edu) +- */ +- +-#ifndef _SPARC_PCONF_H +-#define _SPARC_PCONF_H +- +-#include +-#include +- +-#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 +- + #include + #include + #include +@@ -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 +-#include +-#include +- +-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 +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@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@caip.rutgers.edu) +- */ + #ifndef _SPARC_USER_H + #define _SPARC_USER_H + +-#include +-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@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 +- +-/* +- * 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 +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 ++ ++#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@caip.rutgers.edu) +- */ +- +-#ifndef _SPARC64_PCONF_H +-#define _SPARC64_PCONF_H +- +-#include +-#include +- +-#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 +-#include +-#include +-#include +- +-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 +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@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 ++ ++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 ++ ++#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 +- + #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@caip.rutgers.edu) +- */ +-#ifndef _SPARC64_USER_H +-#define _SPARC64_USER_H +- +-#include +-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 +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 +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 +-#include +-#include +-#include +- +-#include +- +-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 +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 ++ ++/* ++ * 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 + +-#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 + +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 + +-#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 + +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 + #include + #include + +-/** ++/** + * 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 /* 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 + +-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 ++#include + #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 ++#include ++#include ++ ++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 +-#include +- +-#include +-#include +-#include +- +-#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 +-#include +-#include +- +-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 /* need byte IO */ + #include + +- + #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 + + #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 ++ ++#ifdef CONFIG_X86_32 + #include /* for savesegment */ + #include + +@@ -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 +- + /* + * 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 + #include +@@ -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 + + #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@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 ++ + 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 + + #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 + + /* +- * 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 + #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 ++#include + #include + #include + +@@ -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 + +-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 + #include + +@@ -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 ++#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 + ++#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 ++#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 +- */ +-#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 + +-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 +- +-#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 +- +-#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 ++ * ++ * 1998 Tymm Twillman + */ + + /* +- * 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 +- ++ + 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 + #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 + +@@ -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 ++ + #include + + #ifdef CONFIG_X86_32 + #include + +-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 + +-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 + + /** + * __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 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 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 ++#include ++#include ++ ++#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 +-#include +- +-#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 +-#include +- +-/** +- * 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 + #include + + 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 +-#define max_pfn_mapped end_pfn_map + #else + #include +-#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 +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 ++ ++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 + + /* 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 + #include + +- + #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 ++#include /* for struct page */ ++#include ++ ++#ifdef CONFIG_PARAVIRT ++#include + #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 +-#include /* for struct page */ +-#include +-#include +-#include +- +-#ifdef CONFIG_PARAVIRT +-#include +-#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 +-#include +-#include +- +-#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 + */ + +-#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 + #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 + #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 + # define PMD_SIZE (1UL << PMD_SHIFT) +-# define PMD_MASK (~(PMD_SIZE-1)) ++# define PMD_MASK (~(PMD_SIZE - 1)) + #else + # include + #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 + +-/* migration helpers, for KVM - will be removed in 2.6.25: */ +-#include ++/* 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 + #include + #include ++ + #include + #include + #include +@@ -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 + #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 +@@ -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 + +-#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 +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 +- +-#ifdef __KERNEL__ +- +-/* +- * SMP- and interrupt-safe semaphores.. +- * +- * (C) Copyright 1996 Linus Torvalds +- * +- * Modified 1996-12-23 by Dave Grothe 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 +- * 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 +- * 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 +-#include +-#include +-#include +- +-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 +- +-#ifdef __KERNEL__ +- +-/* +- * SMP- and interrupt-safe semaphores.. +- * +- * (C) Copyright 1996 Linus Torvalds +- * +- * Modified 1996-12-23 by Dave Grothe 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 +- * 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 +- * 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 +-#include +-#include +-#include +-#include +-#include +- +-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 ++#include ++#include ++ ++/* ++ * We need the APIC definitions automatically as part of 'smp.h' ++ */ ++#ifdef CONFIG_X86_LOCAL_APIC ++# include ++# include ++# ifdef CONFIG_X86_IO_APIC ++# include ++# endif ++#endif ++#include ++#include ++ ++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 ++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 +-#include +- +-/* +- * We need the APIC definitions automatically as part of 'smp.h' +- */ +-#ifdef CONFIG_X86_LOCAL_APIC +-# include +-# include +-# ifdef CONFIG_X86_IO_APIC +-# include +-# 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 +-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 +-#include +- +-/* +- * We need the APIC definitions automatically as part of 'smp.h' +- */ +-#include +-#include +-#include +-#include +-#include +- +-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 + #include + +-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 + #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<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<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 +- + #endif + ++#include ++ + 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 ++#include ++#include ++#include ++ ++ ++/* ++ * 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 ++ + #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 ++ ++#include ++#include ++ ++#include ++ ++/* 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 + +@@ -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 +-#include +-#include +-#include +- +-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 +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 +- + 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 ++#include ++ ++/* ++ * 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 + * +@@ -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 /* not really needed, later.. */ + #include ++#include + + 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 + #include + #include +-#include + #include + + 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 ++ + 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 + #include + #include +-#include ++#include + #include + #include + +@@ -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 ++ + #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 +- +- +-#define DLM_RESNAME_MAXLEN 64 +- ++#include + + 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 ++#include ++ + #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 ++#include ++ ++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 ++ ++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 ++ ++/* 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 + #include + #include ++#include + + #include + #include +@@ -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<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 + #include + #include ++#include + + #include +-#include + #include + + 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 +- * Copyright (C) 2000 Andre Hedrick +- * +- * This program is free software; you can redistribute 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 ++#include + + 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 + #include + #include +-#include ++#include + #include + #include + +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 + #include + #include ++#include /* Needed for MUTEX init macros */ + + #include +-#include /* 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 + #include + #include +-#include + #include + + #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 + #include + #include +-#include + #include + #endif /* __KERNEL__ */ + #include +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 +- +-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 + #include + ++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 ++ * Copyright 2007 IBM, Inc. ++ * by Konrad Rzeszutek ++ * Copyright 2008 ++ * by Konrad Rzeszutek ++ * ++ * 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 + +-#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 + #include + +-#include +- + #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 + #include + #include +- +-#include + #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 + #include + #include +-#include + + #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 and ++ * Tom Rini ++ * ++ * 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 ++#include ++#include ++ ++#include ++#include ++ ++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 ++#include ++ ++#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 ++ ++#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 + #include + #include +- +-#include ++#include + + 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 ++ ++/* 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 ++ * ++ * 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 ++#include ++ ++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 + #include + #include ++#include + + 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 + #include ++#include + #include + #include + +@@ -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 ++#include ++#ifdef __KERNEL__ + #include ++#endif ++#include + + /* + * 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 ++#include ++ ++/* ++ * 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@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 /* 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 ++#include + #include + + 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 + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + #endif + #include + +@@ -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 ++ ++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 + #include + +@@ -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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++#include ++ ++#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 ++ * ++ * This program is free software; you can redistribute it and/or 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 ++ ++#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 + #include + #include ++#include + #include + #include +-#include + + /* 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@intel.com) ++ * Shaohua Li (shaohua.li@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 ++ ++#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 + ++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 +- +-#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 ++ ++#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 +-#include ++#include + #include ++#include ++#include ++#include + + #include + #include + #include + ++#include ++ + 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 +-#include + #include + #include + #include +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 + + #include +-#include + #include + #include + #include +@@ -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 ++ * ++ * 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 ++#include ++ ++/* 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 ++ ++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->datahead)) +- 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 +-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 ++#include ++#include ++ ++ ++#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 ++ ++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 + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + #include + #include +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 + ++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 + + 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 +- +-#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 +- +-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 +- + #include ++#include ++ ++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 +-#include +- +-#include +- + /* + * 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 ++#include ++ ++#include ++ + /* + * 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 + #include + #include +@@ -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 ++#include ++#include ++#include ++#include ++#include ++#include /* Input device layer */ ++#include ++ ++/* ++ * 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 ++ * ++ * 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 ++#include ++ ++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 + #ifdef CONFIG_VIDEO_V4L1_COMPAT + #include +@@ -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 + +@@ -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 +- +-/* 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 + */ + ++/** ++ * 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<__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 +-#include + #include /* 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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +-#include +-#include +-#include +-#include +- +-/* 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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +-#include +- +-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 + #include + +-#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 + #include + +-#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 + #include + ++#include + #include + #include + #include + #include ++#include + #include + + 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 ++ + /* 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 + + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + + /* 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 +@@ -61,20 +65,16 @@ union nf_conntrack_help { + #include + + #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 ++ ++/* ++ * 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 + #include + #include +-#include + + #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 + #include + #include +-#include + #include /* struct sk_buff */ + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -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 + + /** ++ * 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/ +@@ -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 + #include + #include +-#include + #include + #include + #include +@@ -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 ++ ++#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 + #include +- +-enum ipi_vector { +- XEN_RESCHEDULE_VECTOR, +- XEN_CALL_FUNCTION_VECTOR, +- +- XEN_NR_IPIS, +-}; ++#include + + 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 + #include ++#include + + /* 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 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 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 ++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster ++ */ ++ ++#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 ++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster ++ */ ++ ++#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 +- +-#include +-#include +- +-#include +- +-#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 +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 ++ ++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 ++ * Jerone Young ++ */ ++ ++#ifndef _LINUX_XENCOMM_H_ ++#define _LINUX_XENCOMM_H_ ++ ++#include ++ ++#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 + * +- * 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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include ++#include + #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 + #include + #include +-#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + + /* 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 ++ * ++ * Copyright (C) 2000-2001 VERITAS Software Corporation. ++ * Copyright (C) 2002-2004 Timesys Corporation ++ * Copyright (C) 2003-2004 Amit S. Kale ++ * Copyright (C) 2004 Pavel Machek ++ * Copyright (C) 2004-2006 Tom Rini ++ * 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 ++ * ++ * Contributors at various stages not listed above: ++ * Jason Wessel ( jason.wessel@windriver.com ) ++ * George Anzinger ++ * Anurekh Saxena (anurekh.saxena@timesys.com) ++ * Lake Stevens Instrument Division (Glenn Engel) ++ * Jim Kingdon, Cygnus Support. ++ * ++ * Original KGDB stub: David Grothe , ++ * Tigran Aivazian ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++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 $# */ ++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; ++ ++ /* ++ * $#. ++ */ ++ 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 + #include + #include +-#include + + #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 + #include + #include +-#include + #include + #include + #include +@@ -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 + + #include +-#include + #include + #include + #include +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 + #include + #include +-#include + #include + #include + +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 + #include + #include ++#include ++#include ++#include ++#include + + #include + #include +@@ -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 +@@ -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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++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 + + #include +-#include + #include + + /* 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 + #include + #include +-#include ++#include + #include + #include + #include +@@ -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 + #include + #include +-#include ++#include + #include + #include + #include + #include + ++#include ++ + #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 + #include + #include +-#include ++#include + #include + #include + #include +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 + #include + #include ++#include + + /* + * 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 ++#include ++#include ++#include ++ + #include + #include + #include +-#include +-#include + #include + + +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 ++#include ++#include ++#include ++ ++#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 +-#include +-#include +-#include +- +-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 + #include + #include +-#include + + /* 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 + #include ++#include + + /** + * 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 +- */ +-#include +-#include +-#include +-#include +- +-/* +- * 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 +- * 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 ++#include ++#include ++ ++/** ++ * 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 + #include + #include +-#include // Needed by writeback.h +-#include // Prototypes pdflush_operation() ++#include /* Needed by writeback.h */ ++#include /* Prototypes pdflush_operation() */ + #include + #include + #include +@@ -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 + #include + #include ++#include + + #include + #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 "; + static char vlan_buggyright[] = "David S. Miller "; + +-/* 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 + +-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 + #include + #include ++#include + #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 ++ * ++ * February, 2008 ++ * ++ * Based on: ++ * xt_NFLOG.c, (C) 2006 by Patrick McHardy ++ * ebt_ulog.c, (C) 2004 by Bart De Schuymer ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++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 "); ++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 + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + + 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 + #include + #include ++#include + #include ++#include + + /* + * 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->datahead)) ++ 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 + + #include +-#include + #include + #include + #include +@@ -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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +-#include +- +-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; icount-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; icount; 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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +-#include +-#include +-#include +- +- +-#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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +-#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 +- * Joseph Jezak +- * Larry Finger +- * Danny van Dyk +- * Michael Buesch +- * +- * 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 +-/* for is_broadcast_ether_addr and is_zero_ether_addr */ +-#include +- +-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;idata.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, ":\n"); +- else +- seq_puts(seq, "
:\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 + #include + #include ++#include + + /* + * 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 + #include + #include ++#include ++#include + + #ifdef CONFIG_IPV6 + #include +@@ -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 +-#include + #include + #include + #include +@@ -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 + #include + #include ++#include ++#include + + #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 + # '&&' (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 + #include + #include ++#include + +-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 ++ * (C) 2008 Patrick McHardy ++ * ++ * 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 ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++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 "); ++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 "); + 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 + #include + +-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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++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 "); +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 + #include +-#include + #include + #include + +@@ -19,75 +18,19 @@ + #include + #include + +-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 + #include +-#include + #include + #include + +@@ -18,74 +17,19 @@ + #include + #include + +-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 ++ * (C) 2008 Patrick McHardy ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++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 "); +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 + #include + +-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 + * based on RR's ip_nat_ftp.c and other modules. ++ * (C) 2007 United Security Providers ++ * (C) 2007, 2008 Patrick McHardy + * + * 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 "); + 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 + + #include ++#include + #include + #include + +@@ -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 + + 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 +@@ -21,26 +19,33 @@ + #include + #include + ++/* 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 + #include ++#ifdef CONFIG_IPV6_MROUTE ++#include ++#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 + #include + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#include + + 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 + #include + #include ++#include ++#include + + 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, ++ * LSIIT Laboratory, Strasbourg, France ++ * (c) 2004 Jean-Philippe Andriot, ++ * 6WIND, Paris, France ++ * Copyright (C)2007,2008 USAGI/WIDE Project ++ * YOSHIFUJI Hideaki ++ * ++ * This program is free software; you can redistribute it and/or ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include +-#include + #include + #include + #include +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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + + #include + +@@ -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 + #include ++#include + #include + + #include + #include + +-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 + #include + +-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 + #endif ++#include + + #include + #include +@@ -62,20 +63,9 @@ + #include + + 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 + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -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 : 6to4 support + * Nate Thompson : 6to4 support +- * Fred L. Templin : isatap support ++ * Fred Templin : isatap support + */ + + #include +@@ -52,6 +52,8 @@ + #include + #include + #include ++#include ++#include + + /* + 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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + + #include + +@@ -69,9 +70,6 @@ + #include + #include + +-/* 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 + #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 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; imagic == 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 + + +-/* +- * 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; imagic == 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 + + #include +-#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 + #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 + #include + #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 + #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 + #include + #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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 + #include + #include +-#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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#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 +-#include +-#include +-#include +- +-/* 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 +- * +- * 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 +-#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 +- * +- * 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 +-#include +-#include +-#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 +- * +- * 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 +-#include +-#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 +- * +- * 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 +-#include +-#include +-#include +-#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 +- * Copyright 2004, Instant802 Networks, Inc. +- * Copyright 2005, Devicescape Software, Inc. +- * Copyright 2006-2007 Jiri Benc +- * Copyright 2007, Michael Wu +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#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 +- * Copyright 2007 Johannes Berg ++ * Copyright 2007-2008 Johannes Berg + * + * 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 + #include + #include ++#include + #include + #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 ++#include ++#include ++#include ++#include ++ ++/* 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 ++ * ++ * 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 ++#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 ++ * ++ * 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 ++#include ++#include ++#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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * Javier Cardona ++ * ++ * 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 ++ * Javier Cardona ++ * ++ * 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 ++#include ++#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 ++ * ++ * 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 ++#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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++ * ++ * 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 ++#include ++#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 ++ * Copyright 2004, Instant802 Networks, Inc. ++ * Copyright 2005, Devicescape Software, Inc. ++ * Copyright 2006-2007 Jiri Benc ++ * Copyright 2007, Michael Wu ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#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 ++ * ++ * 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 ++#include ++#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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#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 + #include + #include +-#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 + + #include +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#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 +-#include +-#include +-#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 + #include + #include + #include +@@ -18,7 +19,8 @@ + #include + + #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 + #include + #include ++#include + + #include + #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 + #include + #include +-#include +-#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 + + #include +-#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 + #include +-#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 + + #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 + + #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 + #include + #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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#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 + #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 + #include + +-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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++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 "); ++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 + * based on RR's ip_conntrack_ftp.c and other modules. ++ * (C) 2007 United Security Providers ++ * (C) 2007, 2008 Patrick McHardy + * + * 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 + + #include ++#include + #include + #include + #include +@@ -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 + #include + #include +-#include + #include + + #include +@@ -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 + #include + #include ++#include + #include + #include + +@@ -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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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; irq_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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include +- ++#include ++#include + #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 + #include + #include ++#include + #include + #include + #include +@@ -45,6 +46,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -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,"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 + #include + #include +-#include + #include + #include + #include +@@ -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, "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,"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<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 ++ * ++ * 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 ++#include ++#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 ++ */ ++#include ++#include ++#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<props.aalgo)) || ++ (tmpl->allalgs || (tmpl->aalgos & (1<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 ++#include ++#include ++#include ++#include ++#include ++ ++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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++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 + #include + ++/* 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, +- * James Morris ++ * James Morris + * + * Update: KaiGai, Kohei +- * Replaced the avc_lock spinlock by RCU. ++ * Replaced the avc_lock spinlock by RCU. + * + * Copyright (C) 2003 Red Hat, Inc., James Morris + * + * 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 + #include +@@ -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, +- * Chris Vance, +- * Wayne Salamon, +- * James Morris ++ * Chris Vance, ++ * Wayne Salamon, ++ * James Morris + * + * Copyright (C) 2001,2002 Networks Associates Technology, Inc. + * Copyright (C) 2003 Red Hat, Inc., James Morris + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. +- * ++ * + * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. +- * Paul Moore ++ * Paul Moore + * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. +- * Yuichi Nakamura ++ * Yuichi Nakamura + * + * 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 +@@ -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 ++ * ++ * Copyright (C) 2005 Red Hat, Inc., James Morris ++ * Copyright (C) 2006 Trusted Computer Solutions, Inc. ++ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez ++ * ++ * 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 ++ * ++ */ ++ ++/* ++ * (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 + * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. +- * Paul Moore ++ * Paul Moore + * + * 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 ++ * ++ * This code is heavily based on the "netif" concept originally developed by ++ * James Morris ++ * (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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + * +- * Added conditional policy language extensions ++ * Added conditional policy language extensions + * + * Updated: Hewlett-Packard + * +- * 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 + * This 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 + #include + #include +-#include + + /* 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 and Karl MacMillan + * +- * 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 +- * Tuned number of hash slots for avtab to reduce memory usage ++ * Tuned number of hash slots for avtab to reduce memory usage + */ + + #include +@@ -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 +- * Frank Mayer ++ * Frank Mayer + * + * 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 + #include + #include +-#include + #include + + #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 and Karl MacMillan + * +- * Added conditional policy language extensions ++ * Added conditional policy language extensions + * + * Updated: Hewlett-Packard + * +@@ -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, +- * James Morris ++ * James Morris + * + * Updated: Trusted Computer Solutions, Inc. + * +@@ -11,7 +11,7 @@ + * + * Updated: Frank Mayer and Karl MacMillan + * +- * Added conditional policy language extensions ++ * Added conditional policy language extensions + * + * Updated: Hewlett-Packard + * +@@ -27,7 +27,7 @@ + * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC + * Copyright (C) 2003 Red Hat, Inc., James Morris + * This 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 +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + #include + + #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 + #include + #include +-#include + #include + + #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 + #include ++#include + #include + + /* +@@ -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 + #include + #include ++#include + #include + + #include +@@ -27,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #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 ++ * ++ * This program is free software; 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 ++#include ++#include ++#include ++ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pcsp_input.h" ++#include "pcsp.h" ++ ++MODULE_AUTHOR("Stas Sergeev "); ++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 ++#if defined(CONFIG_MIPS) || defined(CONFIG_X86) ++/* Use the global PIT lock ! */ ++#include ++#else ++#include ++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 ++#include ++#include ++#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 ++#include ++#include ++#include ++#include ++#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 ++#include ++#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 + #include + #include ++#include + + MODULE_AUTHOR("Jaroslav Kysela "); + 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@shustring.com) */ + /* Modified for YMF743 by Keita Maehara */ +@@ -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 and ++ * Jean-Christian Hassler ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "saa7146.h" ++#include "aw2-saa7146.h" ++ ++MODULE_AUTHOR("Cedric Bregardis , " ++ "Jean-Christian Hassler "); ++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 and ++ * Jean-Christian Hassler ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 and ++ * Jean-Christian Hassler ++ * ++ * 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 and ++ * Jean-Christian Hassler ++ * 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 and ++ * Jean-Christian Hassler ++ * ++ * 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 + #include "hda_local.h" + #include ++#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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #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 + #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 + #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 + #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 + #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 + #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 + #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 + #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 +- * +- * This program is free software; 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 +-#include +-#include +- +-/* +- * 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 + * +@@ -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 ++ * 2008 Pavel Hofman ++ * + * + * This 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 + #include + #include ++#include + + #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 + #include "oxygen.h" + #include "ak4396.h" +-#include "cm9780.h" ++#include "wm8785.h" + + MODULE_AUTHOR("Clemens Ladisch "); + 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 +@@ -47,11 +73,14 @@ + #include + #include "oxygen.h" + #include "cm9780.h" ++#include "pcm1796.h" ++#include "cs4398.h" ++#include "cs4362a.h" + + MODULE_AUTHOR("Clemens Ladisch "); +-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 + #include + +-#include +-#include ++#include + #include + + #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@wolfsonmicro.com or linux@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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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, ++ * Copyright: (C) 2007 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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, ++ * Copyright: (C) 2007 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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, ++ * Copyright: (C) 2007 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. ++ */ ++ ++#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, ++ * Copyright: (C) 2007 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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, ++ * Copyright: (C) 2007 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. ++ */ ++ ++#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 + #include + +-#include + #include + #include + #include +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 + #include + +-#include + #include + #include + #include +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 + #include + #include ++#include + #include + + #include +@@ -27,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #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 + #include ++#include + #include + + #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 + #include + #include ++#include + #include + #include + #include +@@ -32,7 +33,6 @@ + #include + + #include +-#include + #include + #include + #include +@@ -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@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 "); +-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), diff --git a/debian/patches/series/1~experimental.1 b/debian/patches/series/1~experimental.1 index ac36cf99e..3203ee0f0 100644 --- a/debian/patches/series/1~experimental.1 +++ b/debian/patches/series/1~experimental.1 @@ -1,3 +1,4 @@ ++ bugfix/all/patch-2.6.25-git9 + debian/version.patch + debian/kernelvariables.patch + debian/doc-build-parallel.patch